Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This is a method:

  def nuts(a, b, c)
  end
A method can take a block (a block is not an object, it's syntax):

  nuts { |a, b, c| ... }
You can capture a block as a Proc:

  foo = proc { |a, b, c| ... }
  foo.call(1, 2, 3)
  
  def nuts(&proc)
    proc.call(1, 2, 3)
  end
  
  nuts { |a, b, c| ... }
There is also a Method object:

  method(:nuts).call(1, 2, 3)
And you can turn a method into a Proc:

  method(:nuts).to_proc.call(1, 2, 3)
Why does it makes sense to have these as different things? Because we want to use return in the blocks:

  def nuts
    @vars.each do |var|
      case var
      when String
        # Returns the method, not the block
        return "Test"
      end
    end
  end


Also, they behave slightly different when it comes to arity:

  def nuts(a, b)
  end
  
  foo = Proc.new { |a, b| }
  
  nuts(1, 2, 3)     # => ArgumentError: wrong number of arguments (3 for 2)
  foo.call(1, 2, 3) # works fine
We also have lambda, which is a Proc that works (almost) as a method: http://samdanielson.com/2007/3/19/proc-new-vs-lambda-in-ruby


I see the problem with return, but is it really important enough to have the confusing multitude of options? I wonder if it could at least be approximated with labels in languages without "blocks" (like break, next, retry and so on).

Also, what will the return do if the block has been defined outside of the method, will it also return from the method?

Anyway, thanks for the clarification. I guess to_proc was what I had been looking for back then when I ran into the problem.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: