Question

Coming from a python background, I'm used to running functions providing only the parameters that I need:

def f(a=1,b=2)
    print a,b

f(b=3) #prints "1 3"

Ruby seems to provide the same syntax for optional parameters:

def f(a=1, b=2)
    puts "#{a} #{b}"
end

But running f(b=3) prints 3 2 instead.

My guess is that it's evaluating b=3 before the function call occurs, and passing it as the first argument.

Is this interpretation correct, and is there a way to call a function providing arbitrary arguments?

Was it helpful?

Solution 2

Notice that all arguments are evaluated prior to a method call. If you do f(b = 3), then value assignment b = 3 takes place first, whose return value is 3, and that is used as the argument, so it is the same as doing f(3). Since you provide only one argument, it will be interpreted as the first argument a, and the default value would be used for b.

You are using the wrong construction. This is the way to do it:

def f a: 1, b: 2
  puts "#{a} #{b}"
end
f(b: 3)
# => 1 3

It is using keyword arguments introduced in Ruby 2.0, as is explained in a page that Arup's answer links to.

Here is a workaround for Ruby 1.8, Ruby 1.9.

def f h = {}
  h[:a] ||= 1
  h[:b] ||= 2
  puts "#{h[:a]} #{h[:b]}"
end
f(:b => 3) # Ruby 1.8
f(b: 3)    # Ruby 1.9
# => 1 3

OTHER TIPS

f(b=3) means a local variable b create with value assignment as 3, then it passed as an argument. Son in your method actual parameter a got value 3, and b goes with its default value 2.

Thus running f(b=3) prints 3 2 instead.

In Ruby when you are calling a method, you are just passing the values to the methods actual argument, no scope to set the value of its actual parameters from method calling area.

You should use Keyword Arguments to meet your need. I wouldn't write the code, as @sawa did it for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top