From: David Richards Date: 2013-01-22T11:25:59+09:00 Subject: Re: Enumerator usage Gary Wright wrote in post #1093103: > On Jan 21, 2013, at 2:20 PM, David Richards > wrote: >> Does this inconsistency result from a parser-level layer of 'syntactic >> sugar'? I'm also getting a sense that a 'block' is a parser-level >> construct, >> and a 'Proc' is an execution-level object. > > I don't think it is stressed enough that a block is a syntactic > structure But it is possible to create a block programmatically during runtime by creating a Proc and converting it to a block with the & operator. > that is *always* part of a method call. This page helped clear up a lot of my confusion: http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/ Now I understand that blocks are a shorthand notation than many Ruby programmers avoid. Depending on the case, using blocks may make the program easier or harder to understand. But more than a mere matter of style, there are performance penalties involved, depending on which constructs are used: http://www.confreaks.com/videos/427-rubyconf2010-zomg-why-is-this-code-so-slow > When a method executes, the block associated with the method call can > be executed implicitly via the 'yield' keyword, or explicitly reified > into a Proc object. Once captured within an Proc object it can be > executed > via the #call or #[] methods on the object (which are instance methods > of the Proc class). And Procs can be converted into blocks, using the '&' operator. multiply = lambda{ |x| x*2 } [1,2,3].map &multiply > The reification (or capture) can be triggered via the block argument in > a formal argument list: > > def foo(arg0, &block) > yield("arg to the block) # call implicit block > block.call("arg to block") # call same block via Proc#call > instance method > block["arg to block"] # call same block via Proc#[] instance > method > end > > or the reification can be triggered on demand: > > def foo(arg0) > if some_condition) > captured = Proc.new # Proc.new without explicit block > captures current implicit block > else > yield("arg to block") # call implicit block > end > end Understood. Here's a cleaned-up version of your example code with example calls: def foo(arg0, &block) yield("arg to yield") # call implicit block block.call("arg to block.call") # call same block via Proc#call instance method block["arg to block[]"] # call same block via Proc#[] instance method end foo(nil){|x| puts(x)} def foo2(arg0) if (arg0) captured = Proc.new # Proc.new without explicit block captures current implicit block captured["Proc.new"] else yield("yield") # call implicit block end end foo2(true) {|x| puts(x)} foo2(false){|x| puts(x)} > Proc objects can also be created via the Kernel#proc method call: > > addition = proc { |a,b| a + b } > multiplication = proc { |c,d| c * d } > > puts addition.call(1,2) # => 3 > puts multiplication.call(2,10) # => 20 > > In these examples, the blocks are syntactically part of the calls to to > the proc method. > > puts addition.class # => Proc > puts multiplication.class # => Proc All understood. It's coming into focus. Thanks. _ Dave -- Posted via http://www.ruby-forum.com/.