From: Gary Wright Date: 2011-04-07T09:45:43+09:00 Subject: Re: Proc#== behaviour (from Ruby-Core) --Apple-Mail-30--440092690 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii On Apr 6, 2011, at 7:41 PM, Adam Prescott wrote: > On Thu, Apr 7, 2011 at 12:17 AM, 7stud -- = wrote: >=20 >> In case you didn't know, procs and lambdas in ruby are a mess. >>=20 >=20 > I knew, at least, ever since I read > http://innig.net/software/ruby/closures-in-ruby.rb Interesting read but it seems like the author creates a bit more = confusion than is necessary. That article repeats the common inaccuracy of treating blocks as = instances of Proc, but this is a category error. The two things are = related but not the same thing at all. I think it clarifies things to = view the term 'block' as a describing a syntactic element of a method = call and not as an instance of Proc. The syntactic element can get = reified into in a instance of Proc (or not) but the syntactic = representation is not itself an instance of Proc. An analogy would be the difference between a literal integer and a = fixnum instance: f1 =3D 16 f2 =3D 0xf f3 =3D 0b10000 Here are three different syntactic representations of a single fixnum = reference. The sequence of characters '16' is not an instance of = Fixnum, nor is '0xf' or '0b10000'. The literals cause the runtime to = produce a reference to an instance of Fixnum but the syntactical = elements are not themselves objects. Similarly for blocks: 3.times { puts 'hip, hip, hooray!' } 3.times do puts 'hip, hip, horray! } The blocks are syntactically part of the method call to times and are = not themselves instances of Proc. And in the following: proc { #block } lambda { #block } Proc.new { #block} The 'magic' is happening in the method calls themselves and not in the = syntactic structure of the method calls, which is completely standard. In the referenced article, the author starts off with: > But then I found out that a > function can't accept multiple blocks -- violating the principle that = closures > can be passed around freely as values. The author's terminology is creating more complexity and perhaps = confusion than is warranted. It is true that a method call can only = have a single block in the same way that a method call can only have a = single argument list. They are both syntactical constructs of a method = call (blocks and argument lists). It is not true that a method can not manipulate multiple closures = (instances of a Proc): def compose(f1, f2, arg) f1.call(f2.call(arg)) end puts compose( lambda {|x| x * 2 }, lambda { |y| y + 1 }, 10 ) Ruby happens to provide a special syntax for creating and passing a = single closure to a method (i.e. the block syntax) but that doesn't = prevent you from creating and passing multiple closures to a method if = that is what is desired. The key point I'm trying to make is that it clarifies things to think of = 'block' as a syntactical term and to think of 'closure' or 'instance of = a Proc' as the actual object that is being manipulated (i.e. passed = around, called, queried and so on). When you look at a method that explicitly captures a block: def iterate(a1, a2, &b) [a1,a2].each(&b) end It is again important to think of '&' as a syntactical construct in the = same way that the parens and commas are part of the syntax of the formal = argument list or of an actual method call. The & isn't some strange = operator that converts or manipulates the proc instances referenced by = b, it is simply a syntactical marker for the block element of the method = syntax. Gary Wright= --Apple-Mail-30--440092690--