From: "Aaron D. Gifford" Date: 2011-03-14T12:47:29+09:00 Subject: Re: send() with a block? On Sun, Mar 13, 2011 at 8:30 PM, Josh Cheek wrote: > It says "Invokes the method identified by symbol, passing it any arguments > specified." A block is an argument... Correct, a block IS an argument, but of a rather unusual type in that it may or may not be explicit in the definition of a method that uses it. HOWEVER, if a method (call it method bar or baz) passes any block it receives on to yet another method (call it method foo), it is best that the documents include this fact. AN EXAMPLE: ## Method foo() may or may not be given a block... def foo(*args) puts "foo(#{args.inspect}) called with" + (block_given? ? '' : 'out') + " a block included." yield *args if block_given? end ## Method bar() does NOT explicitly capture block arguments ## and thus does NOT pass any given block on to foo(): def bar(*args) puts "bar(#{args.inspect}) called with" + (block_given? ? '' : 'out') + " a block included." foo(*args) end ## Method baz() DOES explicitly capture block arguments ## and DOES pass any given block on to foo(): def baz(*args, &block) puts "baz(#{args.inspect}) called with" + (block_given? ? '' : 'out') + " a block included." foo(*args, &block) end bar("some", :args => "for bar", :without => "a block") puts bar("some", :args => "for bar", :with => "a block") { |*a| puts "block passed to bar(): #{a.inspect}" } puts "--" baz("some", :args => "for baz", :without => "a block") puts baz("some", :args => "for baz", :with => "a block") { |*a| puts "block passed to baz(): #{a.inspect}" } SAMPLE OUTPUT FROM ABOVE EXAMPLE: bar(["some", {:args=>"for bar", :without=>"a block"}]) called without a block included. foo(["some", {:args=>"for bar", :without=>"a block"}]) called without a block included. bar(["some", {:args=>"for bar", :with=>"a block"}]) called with a block included. foo(["some", {:args=>"for bar", :with=>"a block"}]) called without a block included. -- baz(["some", {:args=>"for baz", :without=>"a block"}]) called without a block included. foo(["some", {:args=>"for baz", :without=>"a block"}]) called without a block included. baz(["some", {:args=>"for baz", :with=>"a block"}]) called with a block included. foo(["some", {:args=>"for baz", :with=>"a block"}]) called with a block included. block passed to baz(): ["some", {:args=>"for baz", :with=>"a block"}] THINGS TO NOTE FROM THE EXAMPLE: * Notice that even though bar() uses the splat to capture and pass through all supplied arguments, because it does NOT explicitly include a &block argument, it does NOT automatically pass through any provided block.= * Note that baz() DOES explicitly include a &block argument and explicitly passes it through. When I read documents and see a method that does NOT explicitly mention a block, I assume that it will NOT pass any supplied block on to yet another method. Hence, I expect that the send() documentation really should mention that any block passed to it IS passed through to the method specified as the first argument to send(). Maybe I'm eccentric, but I prefer that documentation for a method which uses a block, either directly or by passing it through to another method, whether the block is explicit or implicit in the method definition, to clearly document what the block is used for or what is done with it. Aaron out.