davideisinger.com

My personal website
Log | Files | Refs | README

index.md (2685B)


      1 ---
      2 title: "Convert a Ruby Method to a Lambda"
      3 date: 2011-04-26T00:00:00+00:00
      4 draft: false
      5 canonical_url: https://www.viget.com/articles/convert-ruby-method-to-lambda/
      6 ---
      7 
      8 Last week I tweeted:
      9 
     10 > Convert a method to a lambda in Ruby: lambda(&method(:events_path)).
     11 > OR JUST USE JAVASCRIPT.
     12 
     13 It might not be clear what I was talking about or why it would be
     14 useful, so allow me to elaborate. Say you've got the following bit of
     15 Javascript:
     16 
     17 ```javascript
     18 var ytmnd = function() {
     19   alert("you're the man now " + (arguments[0] || "dog"));
     20 };
     21 ```
     22 
     23 Calling `ytmnd()` gets us `you're the man now dog`, while
     24 `ytmnd("david")` yields `you're the man now david`. Calling simply
     25 `ytmnd` gives us a reference to the function that we're free to pass
     26 around and call at a later time. Consider now the following Ruby code:
     27 
     28 ```ruby
     29 def ytmnd(name = "dog")
     30   puts "you're the man now #{name}"
     31 end
     32 ```
     33 
     34 First, aren't default argument values and string interpolation awesome?
     35 Love you, Ruby. Just as with our Javascript function, calling `ytmnd()`
     36 prints "you're the man now dog", and `ytmnd("david")` also works as
     37 you'd expect. But. BUT. Running `ytmnd` returns *not* a reference to the
     38 method, but rather calls it outright, leaving you with nothing but Sean
     39 Connery's timeless words.
     40 
     41 To duplicate Javascript's behavior, you can convert the method to a
     42 lambda with `sean = lambda(&method(:ytmnd))`. Now you've got something
     43 you can call with `sean.call` or `sean.call("david")` and pass around
     44 with `sean`.
     45 
     46 BUT WAIT. Everything in Ruby is an object, even methods. And as it turns
     47 out, a method object behaves very much like a lambda. So rather than
     48 saying `sean = lambda(&method(:ytmnd))`, you can simply say
     49 `sean = method(:ytmnd)`, and then call it as if it were a lambda with
     50 `.call` or `[]`. Big ups to
     51 [Justin](https://www.viget.com/about/team/jmarney/) for that knowledge
     52 bomb.
     53 
     54 ### WHOOOO CARES
     55 
     56 All contrivances aside, there are real-life instances where you'd want
     57 to take advantage of this language feature. Imagine a Rails partial that
     58 renders a list of filtered links for a given model. How would you tell
     59 the partial where to send the links? You could pass in a string and use
     60 old-school `:action` and `:controller` params or use `eval` (yuck). You
     61 could create the lambda the long way with something like
     62 `:base_url => lambda { |*args| articles_path(*args) }`, but using
     63 `method(:articles_path)` accomplishes the same thing with much less line
     64 noise.
     65 
     66 I'm not sure it would have ever occurred to me to do something like this
     67 before I got into Javascript. Just goes to show that if you want to get
     68 better as a Rubyist, a great place to start is with a different language
     69 entirely.