25

I want to do something similar to this:

def creator()
        return lambda { |arg1, arg2 = nil|
                puts arg1
                if(arg2 != nil)
                        puts arg2
                end
        }
end

test = creator()

test('lol')
test('lol', 'rofl')

I get a few syntax errors:

test.rb:2: syntax error
        return lambda { |arg1, arg2 = nil|
                                 ^
test.rb:3: syntax error
test.rb:7: syntax error
test.rb:14: syntax error

is this possible in ruby? i want to set a default value for a parameter to a lambda function

asdasd
  • 261
  • 1
  • 3
  • 3

2 Answers2

49

In Ruby 1.9+, you can use either of the old-style lambdas or the new "arrow" lambda syntax to set a default parameter:

ruby-1.9.1-p378 > f = lambda {|x, y=1| puts(x+y) }
 => #<Proc:0x000001009da388@(irb):4 (lambda)> 
ruby-1.9.1-p378 > f.call(1)
2
 => nil 
ruby-1.9.1-p378 > f.call(1,5)
6
 => nil 

ruby-1.9.1-p378 > f = ->(a, b=5) { puts(a+b) }
 => #<Proc:0x00000100a0e1b0@(irb):1 (lambda)> 
ruby-1.9.1-p378 > f.call(1)
6
 => nil 
ruby-1.9.1-p378 > f.call(1,2)
3
 => nil 
Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
  • 5
    Careful, passing nil won't trigger the default: – mmell Sep 04 '12 at 21:29
  • In Ruby 1.9.3 I get a syntax error when putting a space between the stabby lamba and the parenthesis `f -> (x = 123) {...}`. It works fine without space `f ->(x = 123) {...}`. – Wizard of Ogz Aug 03 '13 at 14:18
  • for `l =->(k,v,r=nil){}` raise an ArgumentError when `{a:"A"}.each &l` but no error when `{a:"A"}each{|k,v| l.call(k,v) }` – Ivan Black Mar 15 '14 at 17:39
15

In Ruby 1.8.x you can sort of fake it along the lines of:

def creator
  lambda do |*args|
    raise ArgumentError if args.empty? || args.size > 2
    arg1, arg2 = args
    puts arg1
    puts arg2 unless arg2.nil?
  end
end

>> test = creator
=> #<Proc:0x000000010125e138@(irb):2>
>> test.call("foo")
foo
=> nil
>> test.call("foo", "bar")
foo
bar
=> nil
>> test.call("foo", "bar", "baz")
ArgumentError: ArgumentError

Edit: The above example defaults the second argument to nil, but if you wish to have another default you can assign arg2 based on args.size (e.g. arg2 = mydefault if args.size < 2). Similarly if you have more than two arguments the unspecified ones will default to nil unless you assign them yourself.

For Ruby 1.9+ see other answers.

Arkku
  • 41,011
  • 10
  • 62
  • 84