Method vs proc vs lambda

All. The. Time.

Modules are both used for namespacing, such as

module MyApp
  class Foo; end
end

module SomeOtherApp
  class Foo; end
end

and for DRY’ing up your code.

module HasArticle
  def article
    @_article ||= Article.find(params[:article_id]
  end
end

class Controller1
  include HasArticle
end

class Controller2
  include HasArticle
end

Take the time to grok them!

You can also use the method method.

#lambda
square_root = -> (i) { Math.sqrt(i) }
p 5.times { |i| square_root.call(i) }

#method
square_root_method = Math.method(:sqrt)
p (1..5).map(&square_root_method)

Taken from this interesting article: Fun With the method Method

When you pass in the block with &, you’re converting it to a proc. The important point is that a proc and a lambda are different (lambda is actually a subclass of proc), specifically in how they deal with return.

So your refactored code is actually the equivalent of:

p = Proc.new { return 10;}
def lab(block)
  puts 'before'
  puts block.call
  puts 'after'
end
lab p

which also generates a LocalJumpError.

Here’s why: A proc’s return returns from its lexical scope, but a lambda returns to its execution scope. So whereas the lambda returns to lab, the proc passed into it returns to the outer scope in which it was declared. The local jump error means it has nowhere to go, because there’s no enclosing function.

The Ruby Programming Language says it best:

Procs have block-like behavior and lambdas have method-like behavior

You just have to keep track of what you’re using where. As others have suggested, all you need to do is drop the return from your block, and things will work as intended.

Thank you. I understand :slight_smile: .

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.