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