Charles Oliver Nutter wrote:
Attached is a patch that alters yield to always accept IRubyObject[],
like a normal call, and changes all callers and implementations to
handle that fact. There are ups and downs to this:
How frustrating. It seems the downs are greater than I realized, and
this actually makes it *more* difficult to compile multiple assignment
instead of less. I'll try to explain.
Ruby's multiassignment semantics allow for some pretty crazy nesting of
arrays within arrays. Complicating matters, multiple assignment will
attempt to coerce non-array values to arrays when possible. Witness!
X.to_ary # => [1, 2, 3, 4]
a, (b, c, *d), (q, r, s), (t, u), *e = 2, X.new, [5, 6], 7, 8;
Let's walk through the logic here:
perform multiple assignment
first element is 'local assign to a', assign first element in array (2)
second element is multiple assignment
retrieve next element
next element is not an array, try to coerce
coerce successful, use that array
perform multiple assignment
first element is local assign to b, assign first element (1)
second element is local assign to c, assign second element (2)
third element is restarg, assign remaining elements ([3, 4])
done with multiple assignment
third element is multiple assignment
retrieve next element
next element is an array, use it directly
perform multiple assignment
first element is local assign to q, assign first element (5)
second element is local assign to r, assign second element (6)
third element is local assign to s, no more elements so assign nil
done with multiple assignment
fourth element is multiple assignment
retrieve next element
next element is not an array, try to coerce
element can't be coerced, just wrap in an array
perform multiple assignment
first element is local assign to t, assign first element (7)
second element is local assign to u, no more elements so assign nil
fifth element is restarg, assign remaining elements in array ([8])
Simple, right?
So the change I made actually throws a wrench into this process. By
making Block.yield accept an array of arguments, I introduce a new type
into the assignment logic. Rather than everything either being an
assignable element, a coercible element, or an array, there's now
IRubyObject[] to consider.
This makes it trickier to process arguments. Of course the assignment
logic as it exists now actually constitutes a bit of a performance
hassle. Since it always has to walk the elements and perform different
logic for them based on the type of params and the structure of the
incoming data, there's a lot of processing done again and again.
Reducing the incoming structure to an IRubyObject[] eliminates the need
to construct a RubyArray to wrap it, but that's about it. We still need
to be able to handle RubyArrays as they're encountered in the data, so
the logic can't be simplified as a result. Bottom line...we can't just
use IRubyObject[] throughout the masgn process.
So then we need something else to optimize assignment. It seems like
backing down my change might make sense (unfortunately) but I have other
plans for optimization. If have any ideas here...I'd love to hear them.
- Cahrlie
---------------------------------------------------------------------
To unsubscribe from this list please visit:
http://xircles.codehaus.org/manage_email