Proc vs lambda vs proc

Hi group(and probably ruby-talk list - is it running btw?).

I got a question on Proc.new and lambda { ... }. AFAIK, there's two
differences between Proc.new(=proc) and lambda. The first one is that
Proc.new does not check the number of arguments passed to it while
lambda does. The secondis that lambda returns as we expect, i.e., it
returns value, while Proc.new does not.

Though Proc.new lacks several advantages that lambda has, I guess
there might be some situation where Proc.new is more suitable than
lambda. As an example, some code blocks that have to executed
thousands times might run more faster than lambda because it does not
have to check the # of arguments, thereby decreasing computational
overhead.

What is your opinion?

Sincerely,
Minkoo Seo

I got a question on Proc.new and lambda { ... }. AFAIK, there's two
differences between Proc.new(=proc) and lambda.

I think you have it slightly wrong: "proc" and "lambda" are aliases while "Proc.new" works different.

> The first one is that

Proc.new does not check the number of arguments passed to it while
lambda does.

Correct:

irb(main):001:0> f1 = Proc.new {|a,b|a+b}
=> #<Proc:0x003bb2d0@(irb):1>
irb(main):002:0> f2 = proc {|a,b|a+b}
=> #<Proc:0x003b1690@(irb):2>
irb(main):003:0> f3 = lambda {|a,b|a+b}
=> #<Proc:0x003a4d3c@(irb):3>
irb(main):004:0> f1[1,2]
=> 3
irb(main):005:0> f1[1,2,3]
=> 3
irb(main):006:0> f2[1,2,3]
ArgumentError: wrong number of arguments (3 for 2)
         from (irb):2
         from (irb):6:in `'
         from (irb):6
irb(main):007:0> f3[1,2,3]
ArgumentError: wrong number of arguments (3 for 2)
         from (irb):3
         from (irb):7:in `'
         from (irb):7
irb(main):008:0> f2[1,2]
=> 3
irb(main):009:0> f3[1,2]
=> 3

> The secondis that lambda returns as we expect, i.e., it

returns value, while Proc.new does not.

I do not understand what you mean here. All three return what you expect (apart from an exception in the case of wrong # of arguments.

Though Proc.new lacks several advantages that lambda has,

Which advantages do you refer to?

> I guess

there might be some situation where Proc.new is more suitable than
lambda. As an example, some code blocks that have to executed
thousands times might run more faster than lambda because it does not
have to check the # of arguments, thereby decreasing computational
overhead.

I suggest to benchmark a concrete example if you are interested in timings. My guess is that the parameter checking overhead is negligible.

What is your opinion?

I usually use lambda because it most resembles the term "lambda expression". But I guess this is just a matter of taste / personal preference.

Kind regards

  robert

···

On 04.02.2007 04:55, Minkoo Seo wrote:
         from :0

Minkoo Seo wrote:

[...]
The secondis that lambda returns as we expect, i.e., it
returns value, while Proc.new does not.

[...] I guess
there might be some situation where Proc.new is more suitable than
lambda. [...]

lambda and Proc.new do handle the return statement in different ways.
Return in lambda returns from the lambda, treating the lambda as an
anonymous function.

Return in Proc.new returns from the enclosing method, treating the block
as an inline piece of code.

The Proc.new behavior is useful where the block is simply a bit the
algorithm. For example:

  def member?(target, list)
    list.each do |item|
       return true if target == item
    end
    false
  end

The explicit return should return from the member? method, not just from
the loop.

-- Jim Weirich

···

--
Posted via http://www.ruby-forum.com/\.

Robert Klemme:

···

On 04.02.2007 04:55, Minkoo Seo wrote:

I got a question on Proc.new and lambda { ... }. AFAIK, there's two
differences between Proc.new(=proc) and lambda.

I think you have it slightly wrong: "proc" and "lambda" are aliases
while "Proc.new" works different.

This is true for Ruby 1.8, but was changed in Ruby 1.9. The decision was
taken because proc and Proc.new are lexically too similar to have different
meanings, IIRC.

Kalman

Okay. The problem is that I am writing a ruby tutorial for people from
other langauges (like C++ or Java), but there are three seemingly same
things: block, proc, and lambda. So I need to write about not only the
differences but also the simple but effective rule for choosing one
out of three.

To make it worse, the functionality provided by proc and lambda is
quite similar except for the differences in parameter checking and
return statement handling. And many people suggest to use lambda
instead of proc if one does not have any particular reason. So what
I'd like to do is to verify whether the preference for lambda is
correct or not.

So, my intention is to find out whether there are people who prefer
Proc to lambda whatever the reason is. Up to now, I see none. Any one?

Sincerely,
Minkoo Seo

···

On Feb 4, 8:18 pm, Robert Klemme <shortcut...@googlemail.com> wrote:

On 04.02.2007 04:55, Minkoo Seo wrote:
> there might be some situation where Proc.new is more suitable than
> lambda. As an example, some code blocks that have to executed
> thousands times might run more faster than lambda because it does not
> have to check the # of arguments, thereby decreasing computational
> overhead.

I usually use lambda because it most resembles the term "lambda
expression". But I guess this is just a matter of taste / personal
preference.

Kind regards

        robert

Minkoo Seo wrote:
> [...]
> The secondis that lambda returns as we expect, i.e., it
> returns value, while Proc.new does not.

lambda and Proc.new do handle the return statement in different ways.
Return in lambda returns from the lambda, treating the lambda as an
anonymous function.

Return in Proc.new returns from the enclosing method, treating the block
as an inline piece of code.

The Proc.new behavior is useful where the block is simply a bit the
algorithm. For example:

I guess the following block (do |item| ... end)

  def member?(target, list)
    list.each do |item|
       return true if target == item
    end
    false
  end
The explicit return should return from the member? method, not just from
the loop.

-- Jim Weirich

is block and not a proc.

AFAIK, block is not converted to proc unless the block is captured by
parameter like &blk. Am I wrong?

Sincerely,
Minkoo Seo

···

On Feb 5, 4:37 am, Jim Weirich <j...@weirichhouse.org> wrote:

Hi --

···

On Sun, 4 Feb 2007, Kalman Noel wrote:

Robert Klemme:

On 04.02.2007 04:55, Minkoo Seo wrote:

I got a question on Proc.new and lambda { ... }. AFAIK, there's two
differences between Proc.new(=proc) and lambda.

I think you have it slightly wrong: "proc" and "lambda" are aliases
while "Proc.new" works different.

This is true for Ruby 1.8, but was changed in Ruby 1.9. The decision was
taken because proc and Proc.new are lexically too similar to have different
meanings, IIRC.

Yes -- this was something that was raised at RubyConf in 2002 or 2003,
and Matz agreed that having proc != Proc.new, while proc == lambda,
was confusing.

David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Thanks for the heads up! Me not being an early adopter tested with 1.8 only. At least I don't have to change my habit of using "lambda". :slight_smile:

Kind regards

  robert

···

On 04.02.2007 12:28, Kalman Noel wrote:

Robert Klemme:

On 04.02.2007 04:55, Minkoo Seo wrote:

I got a question on Proc.new and lambda { ... }. AFAIK, there's two
differences between Proc.new(=proc) and lambda.

I think you have it slightly wrong: "proc" and "lambda" are aliases while "Proc.new" works different.

This is true for Ruby 1.8, but was changed in Ruby 1.9. The decision was
taken because proc and Proc.new are lexically too similar to have different
meanings, IIRC.

I found the following:
http://innig.net/software/ruby/closures-in-ruby.rb
to be an interesting read on the different flavors of closures in
ruby; I think it takes into account some of the 1.9 changes, but it
may be slightly outdated...

-P

···

On 2/5/07, Minkoo Seo <minkoo.seo@gmail.com> wrote:

On Feb 5, 4:37 am, Jim Weirich <j...@weirichhouse.org> wrote:
> Minkoo Seo wrote:
> > [...]
> > The secondis that lambda returns as we expect, i.e., it
> > returns value, while Proc.new does not.
>
> lambda and Proc.new do handle the return statement in different ways.
> Return in lambda returns from the lambda, treating the lambda as an
> anonymous function.
>
> Return in Proc.new returns from the enclosing method, treating the block
> as an inline piece of code.
>
> The Proc.new behavior is useful where the block is simply a bit the
> algorithm. For example:
>

I guess the following block (do |item| ... end)

> def member?(target, list)
> list.each do |item|
> return true if target == item
> end
> false
> end
> The explicit return should return from the member? method, not just from
> the loop.
>
> -- Jim Weirich

is block and not a proc.

AFAIK, block is not converted to proc unless the block is captured by
parameter like &blk. Am I wrong?

Sincerely,
Minkoo Seo

This thread caused me to do some experimenting and I came across some
Proc semantics that I hadn't seen discussed before and that might
be useful in a DSL context. Consider:

class A
   Foo = define_method(:foo) { |x|
     p "self: #{self}"
     return 'positive' if x > 0
     'negative'
   }
end

p A::Foo # #<Proc:0x00026520@proc.question:6>
p A::Foo.call(0) # "self: A" "negative"
p A::Foo.call(1) # "self: A" "positive"
p A.new.foo(0) # "self: #<A:0x25ecc>" "negative"
p A.new.foo(1) # "self: #<A:0x25e2c>" "positive"

I was unaware that define_method returned a proc. I was even more
surprised that it appears to be of the lambda "flavor". That is to
say that a 'return' within the block is relative to the block and not
to the scope where the block is defined.

Previously I thought that only Kernel#proc and Kernel#lambda had
the 'magic' property of altering the return semantics of a block.
I understand why this is also necessary for define_method to be
useful, I was just not aware that the resulting proc was accessible
as the return value of define_method.

I was going to ask if there was any way to write a method like
'define_method' that forces any provided blocks to be interpreted
as lambda vs. 'regular' procs. Then I did some more experimenting:

a = Proc.new { return 42 }
a.call # LocalJumpError

b = lambda &a
a.call # 42

This was another surprise for me as I figured that when lambda was
used, the first proc would be 'wrapped' in a new proc with
lambda semantics, something like:

c = lambda { a.call }

But that isn't the case. If you try 'c.call' you'll get the
LocalJumpError again.

I hadn't see this type of transformation before. It might be
useful in some DSL situations:

   class A
     filter {|x| x.to_s } # ok
     filter {|x| return x.to_s } # potential LocalJumpError
   end

If you wrote filter as:

   def A.filter(&b)
     lambda(&b).call(42)
   end

you can avoid the LocalJumpError.

Gary Wright

Hi --

···

On Sun, 4 Feb 2007, Robert Klemme wrote:

On 04.02.2007 12:28, Kalman Noel wrote:

Robert Klemme:

On 04.02.2007 04:55, Minkoo Seo wrote:

I got a question on Proc.new and lambda { ... }. AFAIK, there's two
differences between Proc.new(=proc) and lambda.

I think you have it slightly wrong: "proc" and "lambda" are aliases while "Proc.new" works different.

This is true for Ruby 1.8, but was changed in Ruby 1.9. The decision was
taken because proc and Proc.new are lexically too similar to have different
meanings, IIRC.

Thanks for the heads up! Me not being an early adopter tested with 1.8 only. At least I don't have to change my habit of using "lambda". :slight_smile:

Originally, I think the decision was to deprecate 'proc' entirely --
which would be fine with me, though as long as it's not different from
Proc.new that's OK too.

David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Although certainly interesting, the author seems to have a slightly
too-broad definition of the term closure. He seems to think that
closures must be first-class functions in addition to providing
lexical binding to the environment they were defined in. That's simply
not so.

Further, he seems to be confusing the syntax of Ruby with features.
For example, in a function:
  def foo( *a ); end
You refer to array of values by the variable 'a', not by '*a'; just
so, of course you refer to a block in a function
  def foo( &b ); end
simply as 'b'...he seems hung up that you can't use &b directly.

···

On Feb 5, 8:29 am, "Patrick Fernie" <patrick.fer...@gmail.com> wrote:

I found the following:http://innig.net/software/ruby/closures-in-ruby.rb
to be an interesting read on the different flavors of closures in
ruby; I think it takes into account some of the 1.9 changes, but it
may be slightly outdated...

gwtmp01@mac.com schrieb:

(... useful infos about procs ...)

Very interesting! Thanks for sharing your experiments.

Regards,
Pit

"Patrick Fernie" <patrick.fernie@gmail.com> wrote/schrieb <240187340702050729x57c3c6bcp1431daa7967ce49d@mail.gmail.com>:

I found the following:
http://innig.net/software/ruby/closures-in-ruby.rb to be an
interesting read on the different flavors of closures in ruby;

Very interesting, indeed. BTW, in article
<g1ae84-d67.ln1@faun.hafner.nl.eu.org> I did the same, i.e. defining a
data structure containing *all* of the Fibonacci numbers:
  s = Stream.delay {
    Stream.cons(0, Stream.delay {
                  Stream.cons(1, Stream.map(lambda{|x,y| x+y}, s, s.cdr))})}
(It uses methods posted in article <9oib84-sf6.ln1@faun.hafner.nl.eu.org>.)

Regards
  Thomas

Yes, it's interesting to be reminded of all this again.

Much as I love Ruby, I hate having multiple versions of essentially the same
concept which differ in subtle ways. I would find it more aesthetically
pleasing if a tiny Ruby core could bootstrap the whole language - and it
might make it easier to port (and understand).

Now, I wonder why you couldn't approach this problem from the other
direction: instead of having two or more different types of lambda, which
handle 'return' semantics differently, have a single type of lambda and two
different return statements. For example:

   return val # return from enclosing method
   result val # return from this block only

Internally, you could implement 'return' semantics using catch and throw:

  def foo
    ... some code
  end

  # could be implemented as something like this:

  define_method(:foo) do
    catch(:return) do
      ... some code
    end
  end

  module Kernel
    def return(rc=nil)
      throw(:return, rc)
    end
  end

The other difference concerns arity. I don't see why argument checking can't
be done everywhere, as long as you have the option of explicitly allowing
variable arguments where you want them:

  p1 = Proc.new { |x=nil,y=nil| ... } # accept 2 or fewer args
  p2 = Proc.new { |x, y, *z| ... } # accept 2 or more args
  p3 = Proc.new { |*x| ... } # no more single-arg special case!

That is, use the same argument list handling for a 'def' method definition,
a block, and a Proc/proc/lambda.

Anyway, that's just a couple of random thoughts. No doubt it's only when you
implement such a cut-down language that you'd find out what the pitfalls are
in practice :frowning:

Regards,

Brian.

···

On Tue, Feb 06, 2007 at 04:00:44AM +0900, Pit Capitain wrote:

gwtmp01@mac.com schrieb:
>(... useful infos about procs ...)

Very interesting! Thanks for sharing your experiments.

Hi --

gwtmp01@mac.com schrieb:

(... useful infos about procs ...)

Very interesting! Thanks for sharing your experiments.

Yes, it's interesting to be reminded of all this again.

Much as I love Ruby, I hate having multiple versions of essentially the same
concept which differ in subtle ways. I would find it more aesthetically
pleasing if a tiny Ruby core could bootstrap the whole language - and it
might make it easier to port (and understand).

Now, I wonder why you couldn't approach this problem from the other
direction: instead of having two or more different types of lambda, which
handle 'return' semantics differently, have a single type of lambda and two
different return statements. For example:

  return val # return from enclosing method
  result val # return from this block only

Internally, you could implement 'return' semantics using catch and throw:

def foo
   ... some code
end

# could be implemented as something like this:

define_method(:foo) do
   catch(:return) do
     ... some code
   end
end

module Kernel
   def return(rc=nil)
     throw(:return, rc)
   end
end

The other difference concerns arity. I don't see why argument checking can't
be done everywhere, as long as you have the option of explicitly allowing
variable arguments where you want them:

p1 = Proc.new { |x=nil,y=nil| ... } # accept 2 or fewer args
p2 = Proc.new { |x, y, *z| ... } # accept 2 or more args
p3 = Proc.new { |*x| ... } # no more single-arg special case!

That is, use the same argument list handling for a 'def' method definition,
a block, and a Proc/proc/lambda.

I think the reason for there not being default arguments in code
blocks is the ambiguity of the pipe character:

   {| x=1 | 2 | 3 } # {(x=1) 2 | 3 } or {(x=1|2) 3 } ?

Dave Thomas suggested something at RubyConf 2005 along the lines of:

   def m(a,b,c) # method
   end

   def (a,b,c) # anonymous function
   end

I'm not sure what happened to that; I haven't seen it mentioned much
in discussions of this stuff.

David

···

On Tue, 6 Feb 2007, Brian Candler wrote:

On Tue, Feb 06, 2007 at 04:00:44AM +0900, Pit Capitain wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Now, I wonder why you couldn't approach this problem from the other
direction: instead of having two or more different types of lambda, which
handle 'return' semantics differently, have a single type of lambda and two
different return statements. For example:

   return val # return from enclosing method
   result val # return from this block only

I think Ruby already has this via 'break'. Also, the default behavior
of returning the last expression evaluated in a block is an implicit
'break' in Proc.new procs.

Sometimes you want a Proc to behave like the body of a method (the lambda flavor of procs) and sometimes you want it to behave like the body of
an iterator (the Proc.new flavor of procs).

That is, use the same argument list handling for a 'def' method definition,
a block, and a Proc/proc/lambda.

That seems to be a goal of the 1.9/2.0 line of Ruby as part of 'cleaning up'
the semantics of block argument scope.

I wish there was some better terminology for the two different types
of procs (rather than 'lambda type' and 'Proc.new type'). I think Pickaxe
uses 'raw proc' but I can never remember which type of proc is being
referenced by that phrase.

Gary Wright

···

On Feb 5, 2007, at 4:28 PM, Brian Candler wrote:

But make this into block syntax and you still have potential ambiguities:

   3.times { (i=nil) puts i }

   3.times do (i=nil)
     puts i
   end

(i=nil) is a valid expression/statement in its own right, so you'd need some
more lexical rules to disambiguate this from an argument list. I'd hate more
whitespace-sensitive rules to be added, e.g.

   {(i) ... } # block args
   { (i) ... } # expression :frowning:

Perhaps you use parentheses, and if a block starts with an open-parenthesis
then it's always an argument list. If you want it otherwise, you have to
explicitly avoid it:

   3.times { nil, (a=b, c=d) }

It seems the rest of the ASCII set has been used already; e.g.
angle-brackets would have the same problem.

   3.times { < i = j > 4 > puts i }

Incidentally, I do see a reason for not doing full argument-checking in
blocks: there are methods which pass block arguments which it's convenient
for the block to ignore if it doesn't want them.

   3.times { puts "hello" }
   3.times { |x| puts "hello #{x}" }

You could get around this by:

(a) having different methods which pass or do not pass arguments:

   3.times { puts "hello" }
   3.times_i { |x| puts "hello #{x}" }

(b) making such arguments explicitly ignorable at the caller side, which I
think I prefer. At worst:

   class Integer
     def times(&blk)
       if blk.arity == 1
         ... loop, yield with index
       else
         ... loop, yield without index
       end
     end
   end

Regards,

Brian.

···

On Tue, Feb 06, 2007 at 07:33:20AM +0900, dblack@wobblini.net wrote:

> p1 = Proc.new { |x=nil,y=nil| ... } # accept 2 or fewer args
> p2 = Proc.new { |x, y, *z| ... } # accept 2 or more args
> p3 = Proc.new { |*x| ... } # no more single-arg special case!
>
>That is, use the same argument list handling for a 'def' method
>definition,
>a block, and a Proc/proc/lambda.

I think the reason for there not being default arguments in code
blocks is the ambiguity of the pipe character:

  {| x=1 | 2 | 3 } # {(x=1) 2 | 3 } or {(x=1|2) 3 } ?

Dave Thomas suggested something at RubyConf 2005 along the lines of:

  def m(a,b,c) # method
  end

  def (a,b,c) # anonymous function
  end

I'm not sure what happened to that; I haven't seen it mentioned much
in discussions of this stuff.

What are those different behaviours?
1. Handling of 'return'
2. Handling of arity
3. Anything else?

If it's just (1) and (2), then I just wonder if you could get the different
behaviours using different keywords, so that there's only a single
underlying proc-like object.

As another idea, if we really need different behaviours, it could be an
explicit attribute of the object:

    a = Proc.new(:iterator) { ... }
    b = Proc.new(:method_body) { ... }

    def proc(opt = :iterator)
      Proc.new(opt)
    end

    def lambda(opt = :method_body)
      Proc.new(opt)
    end

    # or is it the other way round??

Regards,

Brian.

···

On Tue, Feb 06, 2007 at 08:20:49AM +0900, gwtmp01@mac.com wrote:

Sometimes you want a Proc to behave like the body of a method (the
lambda flavor of procs) and sometimes you want it to behave like the
body of
an iterator (the Proc.new flavor of procs).

(b) making such arguments explicitly ignorable at the caller side, which I
think I prefer. At worst:

   class Integer
     def times(&blk)
       if blk.arity == 1
         ... loop, yield with index
       else
         ... loop, yield without index
       end
     end
   end

or have a "yieldopt" statement, which does something like

  def yieldopt(*a, &blk)
    blk.arity == 0 ? blk.call() : blk.call(*a)
  end

so the caller is saying that the callee can either have all of the
arguments, or ignore them all.

I can't think of any useful cases where an iterator calls a block with (say)
three arguments, but the block only accepts two and is happy for the third
to be silently ignored.

If the block only accepts one argument, but yield passes more than one, this
is currently treated as another special case:

irb(main):001:0> h = {1=>"one", 2=>"two", 3=>"three"}
=> {1=>"one", 2=>"two", 3=>"three"}
irb(main):002:0> h.each { |k| puts k.inspect }
[1, "one"]
[2, "two"]
[3, "three"]
=> {1=>"one", 2=>"two", 3=>"three"}
irb(main):003:0>

This could be eliminated if people wrote

    h.each { |*k| .. I want an array .. }
    h.each { |k,v| .. I want separate items .. }

which I think makes the intention very clear. Maybe this is already
considered for 1.9

Cheers,

Brian.