From: Stephen Boesch Date: 2011-07-04T00:15:54+09:00 Subject: Re: Are blocks objects? What messages can they handle? --20cf3071cc62f240b804a72bb9cc Content-Type: text/plain; charset=ISO-8859-1 John, although I was not original question author, wanted to thank you for that great explanation and example. stephenb 2011/7/3 John Feminella > A block is a syntactical construct, not an object. A Proc is the > object-ized form of a block. If you want to do something on the block, > you need to turn it into an object first. > > An analogy might be that the string "def" is a syntactical construct > that creates a method, but it is not itself an object. You can't write > "def.(...)" and have it be meaningful in this context. > > > So . . . how does one send a message to the block before it is passed as > > an argument? Is that even possible? > > You could make it a Proc first and pass that instead. For example, say > you have a method which passes some arguments to a block: > > ====== > > def execute(*args, &block); yield *args if block; end > => nil > > > execute(1, 2, 3) { |*args| puts "args are: #{args.inspect}" } > args are: [1, 2, 3] > => nil > ====== > > Instead of supplying the block, you could pass a block argument: > > ====== > > printer = lambda { |*args| puts "args are: #{args.inspect}" } > => # > > > execute(1, 2, 3, &printer) > args are: [1, 2, 3] > ====== > > Since `printer` is an object, you can call whatever methods you'd like > on it before passing it as a block. Of course, you still need to wind > up with something that looks like a block, or else the `yield` won't > work. For example, you might have a Proc that creates `printers` for > you: > > ====== > > printer_factory = lambda { |message_prefix| lambda { |*args| puts > "#{message_prefix}: #{args.inspect}" } } > => # > ====== > > Now we can ask this Proc to create a printer for us, which we'll then > pass into `execute` as a block argument: > > ====== > > execute(1, 2, 3, &printer_factory.("the arguments to this printer are")) > the arguments to this printer are: [1, 2, 3] > ====== > > Make sense? > > ~ jf > -- > John Feminella > Principal Consultant, BitsBuilder > LI: http://www.linkedin.com/in/johnxf > SO: http://stackoverflow.com/users/75170/ > > > > On Sun, Jul 3, 2011 at 10:12, Chad Perrin wrote: > > Stop me if I'm making any unwarranted assumptions here: > > > > Blocks are basically just a special kind of object passed to a method in > > Ruby -- aren't they? > > > > That makes them objects -- right? > > > > So . . . how does one send a message to the block before it is passed as > > an argument? Is that even possible? > > > > I ask based on curiosity and a desire to better understand the language, > > rather than as any kind of need to solve a real-world problem. > > > > -- > > Chad Perrin [ original content licensed OWL: http://owl.apotheon.org ] > > > > --20cf3071cc62f240b804a72bb9cc--