Project

General

Profile

Actions

Feature #2013

closed

[PATCH] a = *b calls b.*@

Added by jeremye (Jeremy Evans) over 15 years ago. Updated about 7 years ago.

Status:
Rejected
Target version:
[ruby-core:25192]

Description

=begin
This makes the * operator operate more similarly to the + and - operators. The binary versions of + and - call methods named + and -, while the unary versions call methods named +@ and -@. The binary * operator calls the method named *, but the unary * operator calls the method to_a currently, and used to call to_ary in 1.8.6 (and at some point may have called to_splat).

I think this makes for more consistent behavior, and hopefully it isn't just a foolish consistency. I brought up this idea as a question in Shugo Maeda's presentation at RubyKaigi 2009, and discussed it with Matz at Lone Star Ruby Conf 2009, and he thought the idea had merit.

Here's a basic example how this would look:

class MultiplePersonality
def *@
[self, [self, self]]
end
end

mp = MultiplePersonality.new
p1, mp2 = *mp

This comes with a patch that appears to work from my simple testing, but this is my first time working with the internal ruby code, so I apologize in advance if it doesn't do things correctly.

The patch modifies parse.y so the above is no longer a syntax error. It adds a USTAR token to the parser to represent that *@ token. It modifies the splatting to call *@ instead of to_a. Also, for backwards compatibility, it adds *@ to BasicObject, and has it call to_a if it responds to to_a. This allows code that defines to_a and expects that the unary * operator will call to_a to still work.

This patch is mostly for consistency, but it also allows the programmer to make to_a return one thing, and the unary * operator return something else. I can think of the following use case:

Represents an abstract set of rows in the database

class Dataset
def to_a
retrieve_database_rows
end
def *@
[self]
end
end
dataset = Dataset.new

Explicitly asking for an array means I want

an array of database rows represented by the

dataset.

rows = dataset.to_a

If the dataset had any rows, I want to debug print

each row separately. However, if it did not have

any rows, I want to debug print the dataset itself.

p(*(rows.empty? ? dataset : rows))

I'd like to thank Eleanor McHugh for helping me find the key part of ruby that needed to be modified to support this (in vm_insnhelper.c).
=end


Files

unary_star_op_svn.diff (3.99 KB) unary_star_op_svn.diff jeremye (Jeremy Evans), 08/30/2009 02:53 PM
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0