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

Reply via email to