4

I'm working with ruby and I'm just learning lambdas. I have an array of objects and I want to select certain objects from the array based of different conditions like so:

result = array.select{|ar| ar.number > 4}

I want to put the arguments of the select into a lambda expression i.e. I want to put |ar| ar.number > 4 into a lambda expression. I've tried a few things including:

result = array.select{lambda{|g| g.number > 4}}

But this doesn't work.

I've also tried this:

l = lambda {g.number > 4}
result = array.select{|g| l}

and that also doesn't work. Also I need to pass my lambda express to a function so I don't think the first way I did it would have worked. How would I do this?

user3746602
  • 433
  • 1
  • 6
  • 15
  • As the two answers show you, the part you were missing was specifying the argument to the block for use in its contents. – Phrogz Aug 06 '14 at 23:31

3 Answers3

20

Enumerable#select takes a block, not a lambda. So, you need to pass it a block.

Thankfully, there is an operator which will convert a lambda or proc (and in fact anything which responds to to_proc) to a block: the unary prefix & operator, which is only valid in argument lists (where it converts a proc to a block) and in parameter lists (where it converts a block to a proc).

So, if you have a lambda l, you can pass it as a block to method foo like so:

foo(&l)

Your second problem is that your lambda doesn't take any arguments, but the block passed to select takes one argument, so you need to create your lambda with one argument:

l = lambda {|el| el.number > 4 }

# I prefer this syntax, though:
l = -> el { el.number > 4 }

Putting all that together, we have:

result = array.select(&l)
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
6

To pass a lambda (or a proc) to a method as a block, you have to use the special &syntax:

result = array.select &mylambda

Also, your lambda (or proc) must specify the name for parameters it will receive and use. Thus:

l = lambda { |g| g.number > 4}
result = array.select &l
Phrogz
  • 296,393
  • 112
  • 651
  • 745
huocp
  • 3,898
  • 1
  • 17
  • 29
5

A clean way to do this is to use Ruby's "stabby" lambda syntax:

l = ->(ar) { ar.number > 4 }
result = array.select(&l)

The more "traditional" way to define a lambda is as such:

l = lambda { |ar| ar.number > 4 }
result = array.select(&l)

Note that you don't strictly need to use a lambda; you could also use a proc*:

p = proc { |ar| ar.number > 4 }
result = array.select(&p)

* The main difference between proc and lambda is that lambda will throw an error when passed too few or too many arguments, while proc will ignore it. Another subtle difference is that the return statement inside a proc will cause execution to return both from the closure and the enclosing method (if any).

Community
  • 1
  • 1
user2398029
  • 6,699
  • 8
  • 48
  • 80
  • "Proc" rhymes with "block" and "lambda" is greek, just like "method". Argument binding and `return` in a lambda behave like in a method and in a proc behave like in a block. – Jörg W Mittag Aug 07 '14 at 10:40