Ruby Methods: Def, Arguments and Return Values

These Ruby examples show the syntax of methods. They receive parameters and return values with methods.

Methods. A method optionally receives arguments.

And it returns a value. In Ruby, programs extensively use methods. Iterators are built with methods.

 

 

On classes. We find method on classes (instance methods) and at the top level of programs. And to iterate over a range of numbers, we call a method on an Integer.

 

 

First example. Here we use a method. It accepts one parameter of identifier "value." It returns a value, the result of an expression evaluation—the argument is multiplied by 100.

 

Here: We see a nested method call in the final assignment. We call the calculate() method with an argument of 2.

Return: This returns 200. We then pass that value, 200, to the calculate method again, which again multiplies by 100.

Based on:

Ruby 2

Ruby program that calls method

def calculate(value)
    # Multiply by 100 and return.
    return value * 100
end

# Call calculate method.
result1 = calculate(5)
result2 = calculate(10)
result3 = calculate(calculate(2))

# Print results.
print result1, "\n"
print result2, "\n"
print result3, "\n"

Output

500
1000
20000

Default. Ruby supports default values for parameters. We assign to the parameters within the method definition. Here, the compute method has two parameters. And both have default values.

So: When we call compute with two explicit parameters (5, 5) neither of the defaults are used.

However: When we use just one parameter, the second argument (height) uses the default value of 10.

Finally: We invoke the compute method with no arguments. The defaults are both used. So we get a result of 10 times 10, or 100.

Ruby program that uses default parameters

def compute(width = 10, height = 10)
    # Uses default values for parameters if not specified.
    return width * height
end

# 5 times 5.
puts compute(5, 5)

# 5 times 10.
puts compute(5)

# 10 times 10.
puts compute

Output

25
50
100

Implicit return. An implicit return value is one that is not specified. In Ruby, the last expression evaluated is used as a return value. So we can avoid typing the "return" keyword.

Here: We specify no return keyword in the test method. We call it with two arguments (and omit the parentheses).

Important: This syntax form does not work if we have multiple return statements in a method. The "return" is required.

Ruby program that uses implicit return value

def test(x, y)
    # This expression is evaluated and returned.
    (x * 10) + y
end

# Call test with two arguments.
result = test 5, 10

# Display the result.
# ... (5 * 10) + 10 = 60
puts result

Output

60

Keyword arguments. We can call methods with keyword arguments. To call a method with a keyword, the method def must have the keywords specified in its declaration.

Tip: To specify a keyword argument (in the def itself or the method call) please use a ":" after an identifier in the argument list.

Tip 2: Positional arguments (those specified by position, not keyword) must come before keyword arguments.

Ruby program that uses keyword arguments

def display(name: "?", id: 0, size: 0)
    # Display all keyword arguments.
    print "Name: ", name, "\n"
    print "Id:   ", id, "\n"
    print "Size: ", size, "\n"
end

# Call method with keyword arguments.
display(id: 10, size: 5, name: "cat")

Output

Name: cat
Id:   10
Size: 5

Variable arguments. A method can receive a variable number of arguments. We use a star before the argument name. And that argument becomes an array that stores as many parameters as needed.

Note: This syntax is similar to calling a method with an explicit array. The syntax may be clearer in some contexts.

However: In my experience, using explicit arrays is often better. It makes the usage of the def methods more obvious.

Ruby program that uses variable arguments

def test(*items)
    # Iterate over the elements in the array.
    items.each do |item|
	puts item
    end
end

# Call with three arguments.
test("abc", "def", "ghi")

Output

abc
def
ghi

Alias. A method can be aliased with the alias keyword. When the alias is called, the original method is invoked. This works like a macro. Sometimes using an alias can make code clearer.

Ruby program that uses alias on method

def method()
    puts "Hello"
end

# Alias the identifier "m" to "method"
alias m method

# Call method.
m()

Output

Hello

Begin, end. Ruby supports the BEGIN and END blocks. If we want to ensure some statements run at start or exit time, these statements are useful. They must be in all capital letters.

Note: The positions of BEGIN and END in the source file do not matter. END may be used like an "ensure" statement for an entire file.

Ruby that uses BEGIN, END

# Code in BEGIN is run before anything else.
BEGIN {
    puts(1)
}

# Code in END is run afterwards.
END {
    puts(2)
}

# This is after BEGIN and before END.
puts "Middle"

Output

1
Middle
2

Defined. The "defined?" and undef methods test to see if a method has been defined. We can use defined in an if-statement to see if a method can be invoked.

Note: The question mark means the method is a predicate—it returns true or false.

Undef: With undef we can erase a method and make it no longer accessible. We modify the program during execution.

Ruby that uses defined, undef

def test()
    puts "Hello world"
end

# The test method is now defined.
if defined?(test)
    puts true
end

# Undefine the method.
undef test

# The method is no longer defined.
if !defined?(test)
    puts false
end

Output

true
false

Nil return. An empty method returns nil. It has no statements, so the evaluation result of the last statement cannot be returned.

Ruby that uses empty method, nil

# This empty method returns nil.
def test
end

# Test return value of method.
if test() == nil
    puts true
end

Output

true

Recursion. Recursive methods solve many problems. With them, we implement a brute-force search. So we can determine all ways to count change for a certain amount of money, for example.

Recursion

Tip: When designing recursive algorithms, the memory model of your language is important. Some objects may need to be copied.

 

A summary. Methods are a form of structured programming. They provide easily-reusable blocks of code. With these blocks, we construct more complex logical models.

 

 

Some concepts. We create programs that do nontrivial things, that solve problems. With "defined?" we test whether a method is defined. With recursion we create brute-force solvers.