DEV Community

Hal Friday
Hal Friday

Posted on

Passing Functions as Arguments in Ruby

It can be done! As per my last blog post, with no further ado, here is how you do it:

def first_option
    puts "space jam"
end

def second_option
    puts "dogs rule"
end

def receives_function(func)
   method(func).call
end

receives_function(:first_option)
Enter fullscreen mode Exit fullscreen mode

It is imperative to notice that you must pass the function through as a symbol when you are ready to send it along.

There are a few things about this setup that you may find interesting. When I first started looking into this, I assumed that you could just pass them through normally, using receives_function(first_option). I figured, Ruby is nice right?

Wrong.

Just kidding, I mean Ruby is nice, but it's not magic. Because Ruby is a synchronous language and function calls only require the name of the function, Ruby will read receives_function(first_option) and immediately invoke the first_option method, before it enters receives_function method at all.

So let's dive into the other stuff. The symbol terminology is Ruby's built-in way to allow you to reference a function without calling it. By placing the symbol in the argument for receives_function, we are able to pass all the info along and actually get into the receives_function code block before executing anything.

The next step is to figure out how to call a function which has been sent as a symbol. It gets a little hairy here because once we are inside of the receives_function code block, all we have to work with is a variable called func. Not a symbol at all. This is where Ruby's method method comes into play.

As a side note, googling "Ruby method method" is marginally annoying, so here is the link to the Ruby Docs to save you the time if you're interested.

The method method takes an argument of a symbol and returns information about that symbol. When you pass it a symbol of another method, it will return something like this:

[5] pry(main)> method(func)
=> #<Method: main.first_option>
Enter fullscreen mode Exit fullscreen mode

With this it's saying hey, you passed me a method, and its name is first_option. You can chain a few commands on the end of this return value to determine other information about the symbol. For example, you could add .source_location and it would give you the file name and the line on which the original first_option function was defined. That's very useful for debugging, but in our case we don't care about that -- we just wanna invoke it. So, as you saw in the example, we chain a .call on there and "call" it a day.

Sigh.

So that's that! Have fun out there.

Top comments (3)

Collapse
 
tomboul profile image
Tomboul • Edited

Great Hal Friday !!

I would add a small comment. This is when a function is called, we want to pass the function received as an argument

def first_option (arg)
    puts "space jam for #{arg}"
end

def second_option (arg)
    puts "dogs rule is #{arg}" 
end

def receives_function(func)
   treatFunction(method(func))
end

def treatFunction(callback)
  callback.call("music")
end

receives_function(:first_option)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
k_penguin_sato profile image
K-Sato • Edited

Great post! Thank you!

Collapse
 
ben profile image
Ben Halpern

Very well described. I did not understand this very well.