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}

So really we're talking about either doing away with Ruby's iterator
facility or making it very cumbersome, in exchange for not having to
say "proc" or "lambda" on those (relatively rare) occasions when you
want to pass multiple closures to a method.  (Which I admit makes all
of this completely unacceptable to me as a real possibility, though I
find it interesting to talk about anyway :-)

[...]

> > 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 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 :-)


David

-- 
David Alan Black
home: dblack / candle.superlink.net
work: blackdav / shu.edu
Web:  http://pirate.shu.edu/~blackdav