Larry Wall wrote:
By all accounts, a s/// is an odd thing to put in a smart match
anyway. You can't have a superposition of things with side effects,
for instance:
$str =~ s/a/b/ | s/b/c/
Though doubtless Damian can think of something indeterminate to make
it mean. :-)
Of course. That just superimposes the value in $str. For example:
$str = "abc";
$str =~ s/a/b/ | s/b/c/
print eigenstates $str; # "bbc", "acc"
The in-place really feels more like you want a method
$str.s/a/b/
@foo.s(1|2|3, {0})
or maybe
$str.subst/a/b/
@foo.subst(1|2|3, {0})
This is great, except for how much C<subst> looks like C<substr>.
Maybe:
$str.replace/a/b/
@foo.replace(1|2|3, {0})
???
Maybe the return value form is also a method:
$result = $str.where/a/b/
@result = @foo.where(1|2|3 -> {0})
I like the idea, but the keyword is wrong, I think. Too non-specific.
(No, I don't have a better one off the top of my head ;-)
I would, however, point out that other methods could
potentially have modify-in-place and a copy-and-modify
variants:
@array.splice(2,0,$element); # in-place
@new = @array.splice(2,0,$element); # on copy
$str.chomp; # in-place
$new = $str.chomp; # on copy
$str.lcfirst; # in-place
$new = $str.lcfirst; # on copy
@array.map({ %trans{$^a} }); # in-place
@new = @array.map({ %trans{$^a} }); # on copy
So we might want to look for a more general solution.
Unfortunately, one can't just generalize and use
void/non-void context to determine the correct behaviour,
since in-place matches and substitutions still need to
return their match object:
$matched = $str.replace(/foo/ -> { 'bar' }); # in-place
$newstr = $str.replace(/foo/ -> { 'bar' }); # on copy
One could perhaps change the verb to a participle:
@array.splice(2,0,$element); # in-place
@new = @array.spliced(2,0,$element); # on copy
$str.chomp; # in-place
$new = $str.chomped; # on copy
$str.lcfirst; # in-place
$new = $str.lcfirsted; # on copy
@array.map({ %trans{$^a} }); # in-place
@new = @array.mapped({ %trans{$^a} }); # on copy
$matched = $str.replace(/foo/ -> { 'bar' }); # in-place
$newstr = $str.replaced(/foo/ -> { 'bar' }); # on copy
but I doubt that would be well accepted. ;-)
Or one could define a copy-the-invoke method call operator (say, C<+.>):
@array.splice(2,0,$element); # in-place
@new = @array+.splice(2,0,$element); # on copy
$str.chomp; # in-place
$new = $str+.chomp; # on copy
$str.lcfirst; # in-place
$new = $str+.lcfirst; # on copy
@array.map({ %trans{$^a} }); # in-place
@new = @array+.map({ %trans{$^a} }); # on copy
$matched = $str.replace(/foo/ -> { 'bar' }); # in-place
$newstr = $str+.replace(/foo/ -> { 'bar' }); # on copy
In typical topical string usage, that leaves us with
if .subst/a/b/ {...}
$result = .where/a/b/
That's quite livable, though the second is a bit odd, English-wise.
We could even keep around
s/a/b/
as a shorthand for .subst/a/b/.
Oh, I definitely think so!
And maybe even add
w/a/b/
as a synonym for .where/a/b/.
Hmmmmm. *s*ubstitute and *w*eplace. ;-)
Damian