Monday, May 28, 2012

Lambda Function syntax in Ruby 1.9

Tonight's head-banging incident was directly related to lambda function syntax.  Rather naively I assumed that what I thought would work would work.  As always, assumption makes an ass out of umption.

This works as I would expect
# a simple no-argument lambda
y = -> { 1 * 2 }

This works as I would expect, too
# a lambda that takes one argument and doubles it
z = ->(a) { a * 2}
puts z.(1)
=> 2

However, the important thing to realize is that lambda definitions are whitespace sensitive, whereas a lot of the rest of the language does not seem to be.
 
#     v  <-- note the space below the v
x = -> (a,b) { a * b * 3 }

Ruby really, really doesn't like this space:
C:\Ruby193\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) C:/workspace/ruby-intro/rubymine-intro/modules/closure.rb
-e:1:in `load': C:/workspace/ruby-intro/rubymine-intro/modules/closure.rb:5: syntax error, unexpected tLPAREN_ARG, expecting keyword_do_LAMBDA or tLAMBEG (SyntaxError)
x = -> (a,b) { a * b * 3 }
        ^
    from -e:1:in `<main>'

So remember, lest you also spend some frustrated time going 'WTF' at the ruby interpreter.  Lambdas which take method arguments are WHITESPACE SENSITIVE.

See This StackOverflow question (Spacing around parentheses in Ruby) for more information.

2 comments:

  1. Great catch! I'm swiping this for my NoVaRUG presentation later this month on Ruby Gotchas. :-)

    But.

    If you have a single arg, and leave off the parens, you CAN use a space, a la:

    irb> z = -> a { a * 2}
    => #
    irb> z.(3.2)
    => 6.4

    ReplyDelete