Files
davideisinger.com/content/elsewhere/convert-ruby-method-to-lambda/index.md
2023-10-22 23:52:56 -04:00

64 lines
2.7 KiB
Markdown

---
title: "Convert a Ruby Method to a Lambda"
date: 2011-04-26T00:00:00+00:00
draft: false
needs_review: true
canonical_url: https://www.viget.com/articles/convert-ruby-method-to-lambda/
---
Last week I
[tweeted](https://twitter.com/#!/deisinger/status/60706017037660160):
> Convert a method to a lambda in Ruby: lambda(&method(:events_path)).
> OR JUST USE JAVASCRIPT.
It might not be clear what I was talking about or why it would be
useful, so allow me to elaborate. Say you've got the following bit of
Javascript:
var ytmnd = function() { alert("you're the man now " + (arguments[0] || "dog")); };
Calling `ytmnd()` gets us `you're the man now dog`, while
`ytmnd("david")` yields `you're the man now david`. Calling simply
`ytmnd` gives us a reference to the function that we're free to pass
around and call at a later time. Consider now the following Ruby code:
def ytmnd(name = "dog") puts "you're the man now #{name}" end
First, aren't default argument values and string interpolation awesome?
Love you, Ruby. Just as with our Javascript function, calling `ytmnd()`
prints "you're the man now dog", and `ytmnd("david")` also works as
you'd expect. But. BUT. Running `ytmnd` returns *not* a reference to the
method, but rather calls it outright, leaving you with nothing but Sean
Connery's timeless words.
To duplicate Javascript's behavior, you can convert the method to a
lambda with `sean = lambda(&method(:ytmnd))`. Now you've got something
you can call with `sean.call` or `sean.call("david")` and pass around
with `sean`.
BUT WAIT. Everything in Ruby is an object, even methods. And as it turns
out, a method object behaves very much like a lambda. So rather than
saying `sean = lambda(&method(:ytmnd))`, you can simply say
`sean = method(:ytmnd)`, and then call it as if it were a lambda with
`.call` or `[]`. Big ups to
[Justin](https://www.viget.com/about/team/jmarney/) for that knowledge
bomb.
### WHOOOO CARES
All contrivances aside, there are real-life instances where you'd want
to take advantage of this language feature. Imagine a Rails partial that
renders a list of filtered links for a given model. How would you tell
the partial where to send the links? You could pass in a string and use
old-school `:action` and `:controller` params or use `eval` (yuck). You
could create the lambda the long way with something like
`:base_url => lambda { |*args| articles_path(*args) }`, but using
`method(:articles_path)` accomplishes the same thing with much less line
noise.
I'm not sure it would have ever occurred to me to do something like this
before I got into Javascript. Just goes to show that if you want to get
better as a Rubyist, a great place to start is with a different language
entirely.