2

I'm just starting with Ruby and I hit an issues which I feel is important for the language so I don't want to just pass it. I would really appreciate answer which includes not only a working example but at least brief explanation where I went wrong with mine.

So first step is having this method:

def filter (arr)
    arr.each do |e|
        puts e if e % 2 != 0
    end
end 

filter [1, 2, 3, 4, 5, 6]

And the result as expected is:

1 3 5 [Finished in 0.2s]

Second I tried this one:

def filter (arr)
    arr.each do |e|
        puts e if yield(e)
    end
end 

filter ([1, 2, 3, 4, 5, 6]) { |n| n.odd? }

And I got the same result:

1 3 5 [Finished in 0.2s]

Third I want to do this using a lambda. Ultimately I want ti invoke the filter method like so filter([1, 2, 3, 4, 5, 6], &is_odd). But since I can't still figure it out I am currently stuck at this:

is_odd = lambda { |n| puts n if n.odd? }

def filter ()
    arr = [1, 2, 3, 4, 5, 6]
    arr.each do |e|
        is_odd(e)
    end
end 

filter &is_odd

And I got the following error:

block in filter': undefined methodis_odd' for main:Object (NoMethodError)

It kind of makes sense to me that this is not working since, if I define the lambda inside the filter function and use it like so:

def filter ()
    is_odd = lambda { |n| puts n if n.odd? }
    arr = [1, 2, 3, 4, 5, 6]
    arr.each &is_odd
end 

filter

I'm again getting the expected behavior, but I am following a tutorial and it seems like it should be possible to declare is_odd outside the filter method and invoke filter like so filter([1, 2, 3, 4, 5, 6], &is_odd).

I would like to know if indeed it is possible to do use lambda this way and if yes, where did my logic fail?

1 Answer 1

6

I would like to know if indeed it is possible to do use lambda this way

Yes.

and if yes, where did my logic fail?

By passing the lambda as &is_odd, you're turning it into a block of the method. So, use it as a block. In the snippet above you show that you know about yield. Here's another way of calling the passed block.

is_odd = lambda { |n| puts n if n.odd? }

def filter(&block)
    arr = [1, 2, 3, 4, 5, 6]
    arr.each do |e|
        block.call(e)
    end
end 

filter(&is_odd)
# >> 1
# >> 3
# >> 5
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, I was wondering about this option. Is it OK to include lambdas in method definition?
@Leron: the &block? It's not your lambda anymore. In this case, it's a Proc object, which is made from the method's block (which, in turn, comes from your lambda). And yes, it's a common thing to see in ruby code.
Probably worth noting that you don't use parentheses like that when calling a lambda, hence the NoMethodError. You use brackets (some_lamba[arg]), #call (some_lambda.call(arg)), or dot-parentheses (some_lambda.(arg)).
@muistooshort: ah yes, totally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.