David Alan Black wrote:

> Hi --
> 
> On Tue, 1 Jan 2002, Michael Lucas-Smith wrote:
> 
> 
>>Joel VanderWerf wrote:
>>
>>>>>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.
>>
> 
> But the notion of "the anonymous block" has been eliminated in this
> scenario -- meaning that this:
> 
>    method_call(arg) { |x| puts x }
> 
> is now what used to be:
> 
>    method_call(arg,lambda{ |x| puts x })  # lambda instead of proc,
>                                           # just for variety :-)
> 
> since the idea is, it appears, to allow arbitrarily many blocks.
> 
> And if you have to put in some extra keyword or whatever to
> distinguish *the* block (the one to which 'yield' yields) from the
> others, then the original purpose is thwarted because you'd end up
> with a lot more extra keywords than you do now with having to write
> "proc".  For example, for every call to Enumerable#each you'd have to
> say:
> 
>    [1,2,3,4].each anon_block {|x| puts x}
> 

Not at all. The block technique still works exactly as before. If you 
have a yieldable block given to a method then 'yield' still works 
exactly the same. You don't have to name an anonymous block. If you pass 
it two anonymous blocks, the method has to be expecting an argument. If 
you pass it three anonymous blocks, it has to be expecting two 
arguments. It can optionally use & to name the anonymous block on the 
implementor side, but not on the sender side.



> [...]
> 
> 
>>>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.
>>
> 
> You're not exactly passing the block, though.  Well, you are -- you
> can grab it and bind it to a variable, if you want -- but the main
> idea of the anonymous block is to assume control when the 'yield'
> statement is encountered.
> 
> Hmmm...  I think yours is the first negative reaction to Ruby's
> iterator facility that I've ever seen :-)  I'd have to say, with great
> conviction if not convincingness, that it really isn't a hack; it's
> very much by design and choice.  As for the OO-ness -- I guess you
> could argue the other way, namely that the 'trick' is really the norm:
> closures (procs) are first-class objects, and you're simply passing
> them around like other objects.
> 

I'm not against the iterative features. I just want them to be flexible. 
What if you need two blocks to effectively iterate? ever seen the method 
inject:into: in Smalltalk? how about hierarchy iteration. first block to 
tell it what method to call to iterate over the children, second block 
to perform the collect/select/reject.


> 
>>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.
>>
> 
> Well... you're sort of piggybacking on the coincidence of {} being
> used for both hash and code block.  I think what you're saying is: the
> hash constructor would no longer exist but the {} proc constructor
> could sort of masquerade as a hash constructor.  That seems awfully
> arbitrary.  After all, you've got:
> 
>   ""    # String constructor
>   []    # Array constructor
>   {}    # Hash constructor
> 
> to choose from :-)
> 

It was just an idea - because someone mentioned that currently there 
might be a problem with the fact that {} is used for blocks and hashs.

Michael