From: Michael Lucas-Smith Date: 2002-01-01T06:43:26+09:00 Subject: [ruby-talk:29898] Re: Proc.class vs yield Joel VanderWerf wrote: > David Alan Black wrote: > >>Hi -- >> >>On Tue, 1 Jan 2002, Joel VanderWerf wrote: >> >> >>>David Alan Black wrote: >>> >>> >>>>Hmmm... I wonder whether part of what you're not liking is the fact >>>>that the {} operator is overloaded: it's a block constructor and also >>>>a hash constructor. So there needs to be a way to deal with things >>>>like: >>>> >>>> some_method( { "hi" }, { "one" => 1 }, { |x| puts x }) >>>> >>>There is still some room to overload {} a bit more. The syntax >>> >>> some_method {|x| x+1} {|y| y-1} >>> >>>has no meaning currently--it's a parse error. Could this syntax be given >>>a meaning so that >>> >>> def some_method(&b1, &b2) >>> end >>> >>>allowed the method to use both blocks? >>> >>What would yield do? >> > > Since you're explicitly converting each block to a proc, you don't need > yield in this case. Maybe yield would look for a third, unobjectified, > block? > That'd be the behaviour I'd expect. yield would still handle the anonymous block. > >>>I'm not sure I'd propose this for RCR, since I haven't seen a use for it >>>that couldn't be handled some other way. But still it would be kinda >>>nice. It would allow you to write control structures a la Tcl: >>> >>That would be a mighty big RC :-) >> >> >>> while {} { >>> >>> } >>> >>> >>I don't know Tcl. What does that structure give you? >> > > In Tcl, { ... } denotes a string without interpolation, like '...' in > Ruby. So if you want to define a C-style for-loop in Ruby, you could, > but it would look like: > > for {$x = 0} {$x < 100} {$x += 1} { > puts $x > } > I think that's not going to add you much extra value. > One problem: to use a local variable, you'd still have to reference it > above the for-loop, or else the references in each of the blocks would > be unrelated. > > Anyway, I still don't see a desperate need for this. When I really need > to pass several blocks, I just use the auxilliary object trick with > instance_eval. That has the advantage of associating a name with each > block, so you don't have to remember the order. > That auxilliary object trick is interesting, but it's like listening to a politician talk, when allowing multiple blocks to be passed to a method gives you a much simplier way of achieving the same goal. It's a crazy limitation, "Yes, we have blocks, but you can only pass one. If you want to pass more than one you have to pass proc's." - that statement in itself doesn't ring object oriented to me, it rings hack. I do think that having the interpreter convert the blocks to procs for you would be good. And I guess I now see some of the problems in achieving that - given that {} is used for two things. But I would almost argue that it's not used for two things. "a" => "b" would return an association. You could consider ',' on association to create a hash, and ',' on hash to add an association. With that in mind: { "a" => :a, "b" => :b } would be an executable block to create you a new hash of objects. The only problem with my example there is that there's an implicit .call to the new block/proc. Michael