0

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?

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

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

5 Comments

Unfortunately I'm getting a syntax error on the function definition: syntax error, unexpected ':', expecting '\n' or ';'. Is this syntax available on ruby 1.8?
@goncalopp Are you using Ruby 2.0.0 ? As Keyword Arguments is available there only.
@ArupRakshit No, I'm still on 1.8 (hard requirement). Is there any workaround?
Ugly, but works - thank you! I hope I'll get to use 2.0 soon
I noticed it works in 1.8 just with f(:b => 3), or even f(:b=>5, :a=>7). And it may be worthwhile to update the definition to def f( h={} ) to accept no arguments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.