Ruby methods have following syntax:

def method_name( parameter1, parameter2 )

end

Ruby methods by default return the last statement in the body. Here is an example:

def fun
  a = 5
  b = 6
  c = 7     # by default return c
end

puts fun                 # it is not necessary to put () with methods

The above line will print 7 as the last statement is always returned

Method parameters
def square(x)
  x*x              # return x*x
end

print square(5)
Default values for parameters

Method parameters can also define default parameters if not provided. Let us update the above code:

def square(x = 5)
  x*x              # return x*x
end

puts square(3)
puts square        # x will be 5 here
puts square(6)
Explicitly returning values

We can also return values from methods by using the return keyword. Here is an example:

def fun(x)
  if x%2 == 0 then
    return "even"
  else
    return "odd";
  end
end

puts fun(5)
Variable number of arguments

We can also pass any number of arguments to the method, without declaring multiple number of parameters. The passed values will be treated as array. Here is an example:

def fun(*numbers)

  for i in 0..numbers.length-1
    puts numbers[i] * numbers[i]
  end

  puts("--------------")
end

fun(2,3,4)
fun(5,6)
fun(7,8,9)
Closure

A closure is a function with following properties:

  1. It can be treated as a variable
  2. It can be passed to methods
  3. It can be assigned to other variables
  4. Remembers variable declared inside its scope
Blocks

Blocks are code containers. They are used to group related code together. A block can be declared like this:

do .. end

or

{ }

Blocks can also be passed to a method. So, when we call a method, we can pass the block.

Here is an example:

def test
  puts "Hi"
  puts "Done"
end

test{ puts "This is block"}   # calling method test and passing the block { .. }

If you run this code, you will see that the block is not called. To execute this block, we write a special keyword called yield. Here is the modified example:

def test
  puts "Hi"
  yield            # execute the passed block
  puts "Done"
end

test{ puts "This is block"}

Another syntax for passing block is:

def test
  puts "Hi"
  yield            # execute the passed block
  puts "Done"
end

test do puts "This is block" end

More examples of block

(1..5).each do |n|
  puts n*n
end

(1..5).each { |n|
  puts n*n
}
Lambda

Lambda is a function without a name that is used to perform quick calculations. You can also call it anonymous function
A lambda can be declared like this:

lambda_name = lambda { }

A normal iteration to square each number can be written as:

(1..5).each do |n|
  puts(n*n)
end

This can be converted to lambda like this:

square = lambda { |x| puts x*x }

(1..5).each &square
[1,2,3,4,5].each &square
Passing lambda’s to methods

We can pass lambda to an existing method. Here is an example:

square = lambda { |x| puts x*x }

def perform(numbers, &operation)
  numbers.each &operation
end

perform [1,2,3,4,5], &square
Procedure or Proc

A proc is an instance of Proc class. This means we call method and assign it to other variables. A proc is very similar to lambda with some minor difference.

  1. Lambda checks the number of arguments passed to it. If there is a mismatch, the program will crash. Proc doesn’t check the number of arguments passed to it.
  2. If there is a return statement inside lambda, the program simply comes out of the lambda code whereas if there is a return statement inside proc, the program comes out of the method in which proc was being executed.

A procedure can be declared with following syntax:

procedure_name = Proc.new { .. }

or

procedure_name = Proc.new do .. end

Here is an example to compare both:

def call_code(code)
   code.call(1, 2)
end

pro = Proc.new {|a,b| puts "You passed %d and %d" % [a, b] }
lam = lambda {|a,b| puts "You passed %d and %d" % [a, b] }

call_code (pro)
call_code (lam)

The output should be same. Now change the line:

code.call(1, 2)

to

code.call(1)

lambda will crash the program whereas proc will not care about lesser number of arguments passed.