Take me home

Method arguments

Written by August Lilleaas, published September 10, 2008

An introduction to the stuff your mom and dad didn't tell you about giving arguments to methods.

The asterisk

Capture x amount of arguments.

def silly_list(*args)
  args.join(' ') + '.'
end

silly_list 'My', 'hovercraft', 'is', 'full', 'of', 'eels'
"My hovercraft is full of eels."

You can also do it the other way around, when calling a method. This will pass each item in the array as a separate argument to the method.

def say_a_name(first, last)
  puts "#{last}, #{first}"
end

name = ['John', 'McClaine']
say_a_name(*name)
# => "McClaine, John"

name = ['John', 'Leethal', 'McClaine']
say_a_name(*name)
# => ArgumentError: wrong number of arguments (3 for 2)

The ampersand

Capture the block.

def can_has_block(&block)
  puts block.inspect
end

can_has_block
# => nil

can_has_block { "Here is a block" }
# => #<Proc:0x0008f138@-:8>

You can also do it the other way around, when calling a method. This will pass the proc to the method as if you were giving it a normal block. The last two calls are identical:

a_proc = Proc.new { puts "I am a proc" }

def call_the_block
  yield
end

call_the_block { puts "I am a block" }
# => I am a block
call_the_block { a_proc.call }
# => "I am a proc"
call_the_block(&a_proc)
# => "I am a proc"

And then, of course, without the ampersand Ruby treats the proc as any other object passed as an argument.

call_the_block(a_proc)
# => ArgumentError: wrong number of arguments (1 for 0)

Both?

Of course! Let's use every trick in the book.

def another_map(*args, &block)
  args.map(&block)
end

another_map('hello', 'there') {|i| i.upcase }
# => ["HELLO", "THERE"]

Yield

Don't forget yield, though. These two calls are identical.

def say_hello(&block)
  block.call
end

def say_hello
  yield
end

In fact, yield is much better, as Ruby doesn't have to instantize a Proc object.

Default values

You probably knew this already.

def a_default_value(value = {})
  value
end

a_default_value
# => {}

a_default_value("hello!")
# => "hello!"

Questions or comments?

Feel free to contact me on Twitter, @augustl, or e-mail me at august@augustl.com.