Equivalent of "Pass" in Ruby

Equivalent of “pass” in Ruby

You always have end statements, so pass is not needed.

Ruby example:

def some_function()
# do nothing
end

Ruby 3.0

As of Ruby 3.0, so-called "endless" method definitions are now supported -- we no longer require end statements with every single method definition. This means the most concise way of expressing an empty method like the example above is now arguably something like this:

def some_function = nil

Alternatively, there has always been an uglier one-line option using the much-hated semicolon:

def some_function; end

Note that this doesn't really change anything about the first solution except how the code can be written.

How to pass by reference in Ruby?

Ruby is strictly pass-by-value, which means references in the caller's scope are immutable. Obviously they are mutable within the scope, since you can assign to them after all, but they don't mutate the caller's scope.

a = 'foo'

def bar(b)
b = 'bar'
end

bar(a)

a
# => 'foo'

Note, however, that the object can be mutated even if the reference cannot:

a = 'foo'

def bar(b)
b << 'bar' # the only change: mutate the object instead of the reference
b = 'baz'
end

bar(a)

a
# => 'foobar'

If the object you get passed is immutable, too, then there is nothing you can do. The only possibilities for mutation in Ruby are mutating the reference (by assignment) or asking an object to mutate itself (by calling methods on it).

You can return an updated value from your method and have the caller assign that to the reference:

a = :foo

def bar(b)
:"#{a}bar"
end

c = bar(a)

c
# => :foobar

Or you can wrap the immutable object in a mutable one and mutate that mutable wrapper:

a = [:foo]

def bar(b)
b[0] = :bar
end

bar(a)

a
# => [:bar]

[This is really the same thing as the second example above.]

But if you can't change anything, then you are stuck.

Python3 Pass Command Equivalent in Ruby

No, when you want something empty, you write nothing in there in
Ruby, since it's empty.

def some_function()
end

No need for any placeholder like "pass" for nothing.

ruby: do nothing (dummy) function

Ruby doesn't have a pass or no-op statement. In your example, that code would work as written, with or without a comment.

If you'd like to make it explicit, a line with just nil or a comment explaining the method would probably be considered conventional.

How to pass operator as a parameter in ruby?

You can use public_send or (send depending the method):

operator = :>
5.public_send(operator, 4)
# true

public_send (as send) can receive a method as String or Symbol.

In case the method you're using isn't defined in the object class, Ruby will raise a NoMethodError.


You can also do receiver.method(method_name).call(argument), but that's just more typing:

5.method(operator).call(4)
# true

Thanks @tadman for the benchmark comparing send and method(...).call:

require 'benchmark'

Benchmark.bm do |bm|
repeat = 10000000

bm.report('send') { repeat.times { 5.send(:>, 2) } }
bm.report('method.call') { repeat.times { 5.method(:>).call(2) } }
end

# user system total real
# send 0.640115 0.000992 0.641107 ( 0.642627)
# method.call 2.629482 0.007149 2.636631 ( 2.644439)

Pass by reference or pass by copy - Ruby Modules

All variables in Ruby are references to objects. You cannot "pass by value" versus "pass by reference" in the same way as you have that choice in C, C++ or Perl. Ruby in fact forces pass by value, there are no options to do otherwise. However, the values that are sent are always references to objects. It's a bit like using C or C++ where all member variables are pointers, or using Perl where you must work with references at all times, even when working with simple scalars.

I think that it is this separation of variable from object data that is confusing you.

A few points:

  • Variable allocation never over-writes other variables that may point to the same object. This is pretty much the definition of pass-by-value. However this isn't meeting your expectations that object contents are also protected.

  • Instance variables, and items in containers (e.g. in Arrays and Strings) are separate variables, and if you send a container you can alter its content directly, because you sent the reference to the container, and that includes the same variables for its contents. I think this is what you mean by "seems to be pass-by reference"

  • Some classes - including those representing numbers, and Symbol - are immutable i.e. there are no change-in-place methods for the number 4. But conceptually you are still passing a reference to the singular object 4 into a routine (under the hood, for efficiency Ruby will have the value 4 encoded simply in the variable's memory allocation, but that is an implementation detail - the value is also the "pointer" in this case).

  • The simplest way to get close to the "pass by value" semantics you seem to be looking for with SampleModule is to clone the parameters at the start of the routine. Note this does not actually cause Ruby to change calling semantics, just that in this case from the outside of the method you get the safe assumption (whatever happens to the param inside the method stays inside the method) that you seem to want:


module SampleModule
def self.testing(o)
o = o.clone
o.test
end
end
  • Technically this should be a deep clone to be generic, but that wouldn't be required to make your example work close to a pass-by-value. You could call SampleModule.testing( any_var_or_expression ) and know that whatever any_var_or_expression is in the rest of your code, the associated object will not have been changed.

Ruby string pass by reference function parameter

I understand ruby does pass by reference for function parameters

Ruby is strictly pass-by-value, always. There is no pass-by-reference in Ruby, ever.

This is simply out of curiosity -- any explanations would be appreciated

The simple explanation for why your code snippet doesn't show the result you would expect for pass-by-reference is that Ruby isn't pass-by-reference. It is pass-by-value, and your code snippet proves that.

Here is a small snippet that demonstrates that Ruby is, in fact, pass-by-value and not pass-by-reference:

#!/usr/bin/env ruby

def is_ruby_pass_by_value?(foo)
foo << <<~HERE
More precisely, it is call-by-object-sharing!
Call-by-object-sharing is a special case of pass-by-value,
where the value is always an immutable pointer to a (potentially mutable) value.
HERE
foo = 'No, Ruby is pass-by-reference.'
return
end

bar = ['Yes, of course, Ruby *is* pass-by-value!']

is_ruby_pass_by_value?(bar)

puts bar
# Yes, of course, Ruby *is* pass-by-value!,
# More precisely, it is call-by-object-sharing!
# Call-by-object-sharing is a special case of pass-by-value,
# where the value is always an immutable pointer to a (potentially mutable) value.

Ruby does however allow mutation of objects, it is not a purely functional language like Haskell or Clean.

Is Ruby pass by reference or by value?

In traditional terminology, Ruby is strictly pass-by-value. But that's not really what you're asking here.

Ruby doesn't have any concept of a pure, non-reference value, so you certainly can't pass one to a method. Variables are always references to objects. In order to get an object that won't change out from under you, you need to dup or clone the object you're passed, thus giving an object that nobody else has a reference to. (Even this isn't bulletproof, though — both of the standard cloning methods do a shallow copy, so the instance variables of the clone still point to the same objects that the originals did. If the objects referenced by the ivars mutate, that will still show up in the copy, since it's referencing the same objects.)

How is Ruby Not Pass-By-Reference in This Example?

Ruby is strictly "pass by value" when you consider what a variable is. It is a pointer to an object. Ruby variables and method parameters can only be of these pointers.

Probably best shown by annotating your example:

# Define and set local variable 'dog' to a pointer to a new Dog object
dog = Dog.new
puts "Dog's initial name: #{dog.name}" # => Dog's initial name: Denver

# Pass the pointer, *by value* to the rename_dog method
rename_dog(dog)

puts "Dog's New name: #{dog.name}" # => Dog's New name: New_Dog_Name

Now you might say "this is a useless, technical, definition of pass by value". I would partially agree. It goes against expectations.

However, it only goes against expectations from languages where you have a choice between pointers to objects and variables which directly represent those objects. In Ruby you never have this choice. The definition of Ruby as pass-by-value is correct, but because everything is a pointer, you have to explicitly clone container objects - or use a method which returns a modified copy - if you want to work on a "separate value".



Related Topics



Leave a reply



Submit