---
title: "Passing Functions as Parameters in Ruby"
description: "As someone who likes writing code in a functional style, I really enjoy passing functions as arguments. Whether in Rust or in JavaScript, first-class functions are very useful. Sadly, as naming a …"
image: https://deterministic.space/ruby-ufcs-og.png
url: https://deterministic.space/ruby-ufcs.html
author: "Pascal Hertleif"
date: 2017-12-17
categories: ["ruby","programming"]
---

# Passing Functions as Parameters in Ruby


As someone who likes writing code in a functional style,
I really enjoy passing functions as arguments.
Whether in Rust or in JavaScript,
first-class functions are very useful.
Sadly, as naming a function/method in Ruby is the same
as calling it with zero parameters,
this at first seems impossible to do.

What you can do is pass ~~closures~~ blocks methods.
E.g., `Array#map` really likes being called with a block:

```ruby
xs = ["lorem", "ipsum", "dolor"]
xs.map { |x| x.size }
```

It's not the same as passing an actual function…
but there is one built-in shortcut:
You can call the methods defined for the item's class
(this calls `String#size`):

```ruby
xs.map(&:size)
```

This works quite well for a lot of cases and is very useful in practice.
This is also probably 95% of what a regular Ruby code will ever need.
But, you know, it wasn't enough.
I had to dig deeper.

The thing is:
I sometimes just want to write simple modules that contain functions.

```ruby
module Foo
  def self.bar(x)
    if x == "lorem"
      "bar"
    else
      "baz"
    end
  end
end
```

I'm not saying this is idiomatic Ruby,
but it often is exactly what I want.
Not a singleton class whose name ends with `Service`, just a module.
Not adding a method to `Integer`, just a function in a ~~namespace~~ module.
Not adding this module as a mixin to a class defined in my application
(and not writing a wrapper class if the item's class is not defined in my application).
And not a `{ |x| Foo::bar(x) }`, I just want `Foo::bar`.

So, is this possible?
Yes, kinda:

```ruby
xs.map(&Foo::method(:bar))
```

The `method` method gives you, well, a [`Method`].
It's meta programming at its finest, and,
aside from obvious things like `arity` and `name`,
has some interesting methods, like `curry`, `owner`, and `source`.
And the official documentation also abbreviates it with "meth".
Just saying.

[`Method`]: https://ruby-doc.org/core-2.3.1/Method.html

But, back to the problem at hand:
Is this ugly as hell and should you never ever use it?
Most likely, yes.

So, how to make it better?
With more weird meta programming, of course!
Let's add a method `$m_fn`
that automatically gives the `Method` of `$m`.
If you liked my rambling on
[doing weird things with Rust traits][trait-shenanigans]
more than my [Rust flavored Ruby][rust-and-ruby] post,
you will love what follows.
If you want to keep your ~~sanity~~ innocence, close this tab right now.

[rust-and-ruby]: https://deterministic.space/rust-and-ruby.html
[trait-shenanigans]: https://deterministic.space/impl-a-trait-for-str-slices-and-slices-of-strs.html

```ruby
module BlackMagic
  def self.included(klass)
    klass.extend(MethodAccessorMacros)
  end
  
  module MethodAccessorMacros
    def method_accessor(method_name)
      self.class.instance_eval do
        Array(method_name).each do
          define_method("#{method_name}_fn".intern) do
            method(method_name.intern)
          end
        end
      end
    end
  end
end
```

Yeah, that  chain of `end` lines
that make even the most experienced LISP programmers blush
is a good indicator of how many tries it took me to get this to work.
But it does work:

```ruby
module Foo
  include BlackMagic

  method_accessor :bar

  def self.bar(x)
    if x == "lorem"
      "bar"
    else
      "baz"
    end
  end
end

xs = ["lorem", "ipsum", "dolor"]

xs.map(&Foo::bar_fn)
# => ["bar", "baz", "baz"]
```

[See it in action here.][repl]

And finally: Should you ever use this? Let's just say I hope you don't need to…

**Update:** It just occurred to me that
people might want to read even more on this
~~weird~~ interesting aspect of Ruby.
Here you go:

- [What does the `&` in `&Foo::bar_fn` even do?](https://www.skorks.com/2013/04/ruby-ampersand-parameter-demystified/)
- [Why does `&(:fn)` work?](https://iain.nl/going-crazy-with-to_proc)
- [Dynamically adding methods (What could possibly go wrong?)](http://ryanangilly.com/post/234897271/dynamically-adding-class-methods-in-ruby)

[repl]: https://repl.it/repls/MonumentalStylishOlingo "repl.it chose the random name Monumental Stylish Olingo for this snippet of code. Very fitting"

