On Wed, Mar 10, 2004 at 05:39:33PM +0100, Juerd wrote:
: Perlists,
: 
: In Perl 5, lc, lcfirst, quotemeta, uc and ucfirst don't mutate.
: chomp and chop do mutate.
: 
: I imagine these will all be methods in Perl 6:
: 
:     $foo.lc
:     $foo.quotemeta
:     $foo.chomp
: 
: I'd like a mutating version of lc, and a non-mutating version of chomp.
: With some nice syntax, if possible.
: 
: If there isn't already such a thing in the making, I hereby suggest to
: re-introduce C<.=>, to mean more or less the same as in Perl 5, but with
: Perl 6's version of the C<.> operator.

Except that C<.> isn't really a binary operator...

On the other hand, draft -1 of A12 has a conjectural

    my Dog $dog .= new()

in it, and that's even further out there, since the .new on the right
would in fact be called on a $dog that is undefined!

: In other words: C<$foo.lc> would not mutate and C<$foo.=lc> would.
: 
:     $foo += 5  ===>  $foo = $foo + 5
:     $foo.=lc   ===>  $foo = $foo.lc
: 
: Makes sense to me.

Yes, but the fact that you had to change the spacing bothers me.

: Especially for C<sort> it would be nice for something like this:
: 
:     @foo.sort  # returns sorted copy
: 
: versus
: 
:     @foo.=sort  # sorts inline
: 
: I think this syntax reads better than Ruby's exclamation point
: (foo.method!), because of the analogy with other mutating operators.

Well, I'd like to reserve postfix:! for factorial in any event.  :-)

The basic problem with .= shows up when you do put the spaces in:

    @foo .= sort()

That makes it look as though sort is a subroutine, and it's not.
That's a direct result of the fact that C<.> is not really a binary
operator.  Rather, it's a kind of "operator sigil" that introduces
a unary postfix operator.  Method calls are really unary postfix
operators that happen to be able to take extra arguments.

And because the op= syntax is really built for binary operators, it
doesn't totally work for unary operators.  Take another unary postfix
operator, for instance, an array subscript:

    @array[$x]

you can't just up and say

    @array[=$x]

to mean

    @array = @array[$x]

to turn it into a mutating operator, because the [$x] wants to
function as a unit, and the = breaks that up.  Similarly, ".sort"
wants to function as a unit, but the = breaks that up, visually and
semantically.

However, having said all that, it turns out that A12 will also introduce
other "dot" variants:

    $obj.?method        # call method if exists, or return undef (0 or 1)
    $obj.*method        # call all base class methods of that name (0 or more)
    $obj.+method        # call all base class methods of that name (1 or more)

So a .=method syntax is not so farfetched.  It analogies to +=, but it's
really still just a prefix to a unary postfix operator, like the other
dot variants.  The interesting question with all of these "dots" is
where spaces are allowed or disallowed.  One could make a case that
people will want to write

    my Car $obj .= new()

rather than being forced to write

    my Car $obj .=new()

It could even be argued that, in the case of this particular operator,
the = is functioning as part of the name, as the ! does in Ruby.  So
if (hypothetically) we allow a space after the ordinary dot

    @array . sort

then we could also allow things like:

    @array . =sort
    $obj   . *initialize
    $obj   . ?maybe

But I dislike

    $variable . meth()

for the same reason I dislike

    $variable .= meth()

because it makes meth look like a subroutine call when it isn't.  Regardless
of how fancy they get, method calls are still postfix operators.  So I'm
inclined to say that the space is only optional before the dot, and you have
to say

    @array .sort
    @array .=sort
    $obj   .*initialize
    $obj   .?maybe

But that still makes

    my Cat $tom .=new()

pretty ugly.  Unfortunately we can't just use topicalization to say

    my Cat $tom = .new()

because most people won't expect simple assignment to break their
current topic.

So another option is to replace = with something that I<does> set the
topic for the right side.  If we used .= for that, then you'd have
to write

    @array .= .sort
    my Cat $tom .= .new()

Doubtless the first would get shortened to

    @array.=.sort

That does admit to constructs like

    $foo .= .*bar

which would assign $foo a list of all the return values of $foo.*bar, or

    $foo .= .?maybe

which would presumably replace $foo with an undefined value if
it couldn't find $foo.maybe.  Those don't seem terribly useful as
mutators though.  They'd be much clearer written out long.

Another approach would be to have some kind of "microtopic" that
represented the left side of an ordinary assignment.  Suppose for
the sake of argument that the microtopic is ^.  Then you could write

    @array = ^.sort;

and a constructor would be

    my Kanga $roo = ^.new()

But that introduces a new concept that doesn't really generalize well.
So forget that.

Yet another approach is to *replace* dot with something that mutates:

    @array!sort
    @array?sort

Either of those would work syntactically in that case, since neither !
nor ? is expected as a binary operator.  However, the unary cases
don't work:

    !sort               means "not sort"
    ?sort               means "did sort work?"

We could prefix *those* with a dot, but .? is already taken.  That leaves

    @array.!sort

which is sort of inside-out Ruby.  But then the constructor doesn't
read so well:

    my Dino $dinah is fossilized .!new()

Constructors really, really want = for visual reasons...

We could do something *really* crazy and say that if the assignment
operator is immediately followed by a dot, that dot topicalizes to
the left side of the equals rather than the current topic.  That
gives us

    @array=.sort

and

    my Dino $dinah is fossilized = .new()

That would mean that if you really wanted the current topic, you'd have
to say things like

    @array = $_.sort
    my Dino $dinah is fossilized = (.new())

I think that would be a bad thing to do to the = operator.

Or we could introduce an =. operator.  In which case the mutators
look like

    @array=.sort
    my Dino $dinah is fossilized =.new()

and the regular $_ topicalized ones look like

    @array = .sort
    my Dino $dinah is fossilized = .new()

But the problem is that those look far too much alike.

So I think we're left with .= as an analog of .* and .?:

    @array .=sort
    my Dino $dinah is fossilized .=new()

Perhaps it's not too bad to allow spaces after the compound dot operators:

    @array . sort
    @array .= sort
    $obj   .? maybe
    $obj   .* initialize
    $obj   .+ initialize

After all, the computer won't get confused that a methodname is required
next.  Except that we also have to figure out what these mean, if anything:

    $obj  .$x           # indirect method name like Perl 5?
    $obj .=$x           # indirect mutating operator
    $obj .?$x           # indirect optional method
    $obj .*$x           # indirect all method
    $obj .+$x           # indirect one or more method

    &obj  .($x)         # sub call on code reference
    &obj .=($x)         # ???
    &obj .?($x)         # ???
    &obj .*($x)         # ???
    &obj .+($x)         # ???

    @obj  .[$x]         # subscript on array reference
    @obj .=[$x]         # replace array with slice of array
    @obj .?[$x]         # ???
    @obj .*[$x]         # ???
    @obj .+[$x]         # ???

    %obj  .{$x}         # subscript on hash reference
    %obj .={$x}         # replace hash with slice of hash
    %obj .?{$x}         # ???
    %obj .*{$x}         # ???
    %obj .+{$x}         # ???

and whether a space is allowed after those dotty operators.  The whole
reason for .(), .[] and .{} in the first place was to make them look
like postfix ops rather than terms.  Allowing space after the dot works
against that.  I suspect all the ones marked ??? are simply disallowed
in any event.  So we could probably get away with allowing space after .=
as a special case.  But maybe we want to discourage that too.

: Please excuse me if this or something like this has already been taken
: care of - I've searched for messages about it, but haven't found
: anything.

It was discussed a long time ago, but nothing substantial came of it.
It certainly needs to be nailed down for A12 though.

Larry

Reply via email to