Last Updated: February 25, 2016
·
4.162K
· johnamican

Ruby and Default Arguments

Here are some tidbits I found trying to break default arguments in Ruby.

Look at this:

def foo(biz=:biz, bar=:bar, bazz)
    [biz, bar, bazz]
end

You can pass optional arguments before required ones. Why would you be able to do this? Well...

irb> foo
ArgumentError: wrong number of arguments (0 for 1)

The arity of the function is 1?

irb> method(:foo).arity
=> -2

Looks like it. (arity returns -n-1 when optional arguments exist, where n is the number of required arguments.)

How do we use foo? We can pass it all optional and required arguments, and it will behave as you'd (probably) expect:

irb> foo(:test, :my, :method)
=> [:test, :my, :method]

If we pass one argument, it replaces the first optional argument:

irb> foo(:howdy)
=> [:biz, :bar, :howdy]

If we pass two arguments, it'll replace the first (and only) optional argument, then the first required argument:

foo(:howdy, :partner)
=> [:howdy, :bar, :partner]

When would this be useful? I'm not sure.

It seems that either all optional arguments must come before all required arguments, or vice versa. The following breaks:

irb> def so(long=:and, thanks=:for, all, the=:fish)
irb> end
SyntaxError: (irb):17: syntax error, unexpected '=', expecting ')'

By the way, you can pass default arguments in a define_method call:

Object.send(:define_method, :bar) do |bizz=:bizz, baz=:baz, buzz=:buzz|
end

However, it reports the wrong arity:

irb> method(:bar).arity
0

Which I've opened an issue for https://bugs.ruby-lang.org/issues/8411