Ruby Functions

In Ruby, a function is a set of statements that performs a specific task and help to organize code and make it reusable. They allow you to break down a complex problem into smaller, more manageable parts. Each function can perform its specific task, and the results can be combined to achieve the desired outcome.

Functions in Ruby are first-class citizens, which means that they can be assigned to variables, passed as arguments to other functions, and returned as values from functions. This feature makes functions more flexible and powerful.

Defining a Function

In Ruby, you can define a function using the def keyword, followed by the function name and parameters in parentheses. The function body is enclosed within the do and end keywords, or within curly braces {}.

def say_hello_to(name) {
  puts "Hello " + name;

The function name should be a descriptive name that reflects what the function does. The parameter names should also be descriptive, and they should reflect the type of data that the function expects to receive.

Calling a Function

After defining a function, you can call it by using its name and passing in any required arguments. The arguments passed to the function should match the number and order of the parameters defined in the function.

say_hello_to("Paul")   # outputs "Hello Paul!"

The function will execute the statements in its body, and it may return a value. The returned value can be assigned to a variable or used as an argument to another function.

Return Value

A function can return a value using the return keyword. If no return value is specified, the function will return the value of the last evaluated statement.

def add(left, right)
  return left + right

In the example above, the function add_numbers takes in two arguments and returns their sum. The return keyword is used to specify the value that should be returned from the function.

Default Parameters

Ruby functions can have default parameter values. If a parameter is not passed when the function is called, the default value will be used. This feature can help simplify function calls and make code more concise.

def say_hello_to(name="World")
  puts "Hello, #{name}!"

say_hello_to() # outputs "Hello, World!"
say_hello_to("Paul") # outputs "Hello, Paul!"

In the example above, the function greet has a default parameter value of "World". If no argument is passed to the function, it will use "World" as the value for the name parameter.

Variable Number of Arguments

Ruby functions can also accept a variable number of arguments using the * operator. This feature allows you to pass in any number of arguments to a function, and the function will treat them as an array.

def sum(*numbers)
  total = 0
  numbers.each { |num| total += num }
  return total

sum(1, 2, 3)        # returns 6
sum(4, 5, 6, 7, 8)  # returns 30

In the example above, the function sum takes in any number of arguments and returns their sum. The *numbers parameter is treated as an array of arguments.

Blocks and Procs

In addition to functions, Ruby also supports blocks and procs. Blocks are a set of statements that can be passed to a function and executed within the context of that function. Procs are similar to blocks, but they can be saved to a variable and reused in multiple contexts.

# Block example
def square(n)
  yield n * n

square(5) { |result| puts result } # outputs 25

# Proc example
multiply_by_10 = { |n| n * 10 }
puts # outputs 50

In the example above, the square function takes in a number and a block, and it executes the block with the square of the number. The multiply_by_10 proc multiplies its argument by 10 and returns the result.

Functions, blocks, and procs are powerful tools that allow you to write more modular and reusable code. By breaking down a complex problem into smaller, more manageable parts, you can create more robust and maintainable code.

Mindtwisting moment: Ruby doesn't have functions

Everything in Ruby is an object, with classes being the blueprints from which objects are created.

The "functions" we created above are in fact methods, on a default, "hidden" object named main. You might have also noticed, in the code above, another "function": puts - it is another example of a main method.

Moreover, everything in your Ruby program occurs in the context of the main object, itself an instance of  Object.