Method Parameters in Ruby
The flexible parameter system used by Ruby methods enables variable-length argument lists, required arguments, optional arguments with default values, and explicit handling of passed code blocks.
The def
keyword is used to define a method, which is then followed by the method name and an optional list of parameter names enclosed in parenthesis. Within the method body, these parameter names function as local variables, and the arguments supplied during method invocation determine their values.
The main categories of Ruby method parameters are described here, with code samples:
Required Parameters
The caller must supply a value for each parameter in the most basic form, which makes them positional and required.
Parameter Type | Definition |
Single Required | A method that accepts one positional argument. |
Multiple Required | A method that accepts two or more positional arguments. |
Code Example (Single and Multiple Required):
# Single required parameter
def say_hello_to(name)
puts "Hello #{name}"
end
say_hello_to('Charles') # Hello Charles
# Multiple required parameters
def greet(greeting, name)
puts "#{greeting} #{name}"
end
greet('Hi', 'Sophie') # Hi Sophie
Output
Hello Charles
Hi Sophie
Default Parameters
You can set the parameters’ default values. When a caller leaves out an argument that corresponds to a parameter that has a default value, the default value is automatically substituted. In the parameter list, the assignment operator (=
) is used to define default values.
Note: In addition to constants, argument defaults can also be arbitrary expressions. When the method is invoked, they are evaluated.
Code Example (Default Parameters):
# Single default parameter
def make_animal_sound(sound = 'Cuack') # 'Cuack' is the default value
puts sound
end
make_animal_sound('Mooo') # Mooo
make_animal_sound # Cuack
# Multiple parameters with defaults
def prefix(s, len=1)
s[0,len]
end
prefix("Ruby", 3) # => "Rub" (len is 3)
prefix("Ruby") # => "R" (len defaults to 1)
Output
Mooo
Cuack
Variable-Length Arguments (Splat Operator *)
An arbitrary number of arguments can be passed into a method by prefixing it with the splat operator (*). Within the method, the parameter name refers to the single Array object that contains these arguments. In a method definition, * can only be used as a prefix for one parameter.
Expanding an array into distinct arguments during method invocation is another use for the splat operator.
Code Example (Defining *rest):
def max(first, *rest)
max = first
rest.each { |x| max = x if x > max }
max
end
puts max(1, 2, 3) #=> first=1, rest=[2, 3]
puts max(5) #=> first=5, rest=[]
Output
3
5
Code Example (Splatting arguments during invocation):
def print_pair (a, b)
puts "#{a} and #{b} are a good couple!"
end
pair = ['Jack','Jill']
print_pair(*pair)
# Expands ['Jack', 'Jill'] into two separate arguments: 'Jack' and 'Jill'
Output
Jack and Jill are a good couple!
Keyword Arguments (Ruby 2.0+)
By enabling the out-of-order passing of arguments using explicit names, keyword arguments contribute to clarity.
The Definition of Keyword Arguments
The definition of a keyword argument is the name followed by a colon. It’s possible that they have default values.
Code Example (Keyword Arguments):
def say(message: "Hello World", before: "<p>", after: "</p>")
puts "#{before}#{message}#{after}"
end
say # => "<p>Hello World</p>"
say after: "</p><hr>", message: "Today is Monday"
# Order of keywords is irrelevant
# => "<p>Today is Monday</p><hr>"
Output
<p>Hello World</p>
<p>Today is Monday</p><hr>
Random Arguments Using Keywords (Double Splat)
A Hash object is created by collecting an arbitrary number of keyword parameters using the double splat operator (**).
Code Example (Double Splat):
def print_options(**args)
puts args
end
print_options(foo: "1", bar: "2")
# => {:foo=>"1", :bar=>"2"}
Output
{foo: "1", bar: "2"}
Additionally, the double splat is used in invocation to extend a hash into keyword arguments for a method call (say(**args)).
Tuple Arguments (Destructuring)
It is possible to provide a method argument that will take an array (or tuple) and instantly destructure its contents into named local variables.
Code Example (Tuple Arguments):
def feed( amount, (animal, food) ) # destructures the second parameter
p "#{amount} #{animal}s chew some #{food}"
end
feed 3, [ 'rabbit', 'grass' ]
# => "3 rabbits chew some grass"
Output
"3 rabbits chew some grass"
Block Arguments ()
The implicit code block given to the method is transformed into a Proc
object by Ruby if the final parameter in a method specification is preceded by an ampersand (&
). After that, the named parameter is assigned this Proc
object.
Using the Proc's.call
method in place of the yield
keyword enables the method to save, modify, or explicitly invoke the block.
Code Example (Accepting a Block as a Proc Argument):
def explicit_block_call(&the_block) # &the_block captures the block as a Proc object
puts "Invoking block directly:"
the_block.call("Ruby") # Explicitly call the Proc object
end
explicit_block_call do |name|
puts "Hello from the block, #{name}!"
end
Output
Invoking block directly:
Hello from the block, Ruby!
Keep in mind that the block argument (&the_block
) needs to come after any positional or splat (*args
) arguments in the method definition.