keats.rb

Borrowing from cdcarter:

>> def method_missing s; s end

Now we can write like the English Romantics:

>> for desires in heaven do not always end or fade
=> :each

What’s the shortest way to get irb to respond as follows?

=> some lovers remain unhappy even in paradise

I’m afraid that it’s not going to be very short. Maybe there’s a better closing line? Bonus if you keep up the rough anapests.

10 responses

  1. What…is going on here.

    irb(main):032:0> desire
    => :desire
    irb(main):033:0> for desire in heaven do end
    => :each
    irb(main):034:0> desire
    => nil
    
  2. That sure is slick. I love how :each comes tumbling out of the for/in syntax.

    Seems like we need a new word to describe sentences that parse as valid Ruby with this trick.

    >> send money or love?
    => :money
    

    Guess that answers the question.

  3. Chris, Klondike: actually, it turns out that the for/in block parameter doesn’t get its own lexical scope at all:

    >> [defined?(q), defined?(r)]
    => [nil, nil]
    >> for q in [] do r=3 end
    => []
    >> [defined?(q), defined?(r)]
    => ["local-variable", "local-variable"]
    

    This is the opposite of obj.each {|| } behavior, even though each is still called. Word on the street is that it’s a special case in MRI.

  4. The way I understood it, we’ve got this basic structure:

    for {foo} in {bar} do
      {block}
    end or {baz}

    To run that code, the Ruby interpreter is going to call the each method on {bar} and pass it the block.

    In the case above, {bar} is the word heaven. The interpreter is going to try and call a method named heaven on Kernel (or Object? I forget) and not find one, invoking our new method_missing, which will return the symbol :heaven.

    It then tries to call each on the symbol :heaven. Since the Symbol class does not define an each method, method_missing is again invoked, returning the symbol :each.

    The block is effectively ignored—our method_missing does not care about it—and you get :each. Because we have a true value, the conditional is short-circuited, and we receive the symbol as our final result.

    Does that sound about right?

  5. Chronic: right. The missing methods are sent to the irb context (main), but our handler gets defined on Object because of the way irb works (this way Symbol gets it too). And regular Enumerable#each returns self, but our method_missing(:each) returns the first param.

    Nick: it’s not auto. Just keeping the discourse level high. :)

  6. Right, cool.

    So I guess this is the answer to your first question…

    >> class Symbol
    >>   def inspect
    >>     'some lovers remain unhappy even in paradise'
    >>   end
    >> end                                                                                                                         
  7. Note that Rubinius supports all this literature already:

    sirb(eval):003> for desires in heaven do not always
    end or fade
    => some lovers remain unhappy even in paradise