Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

s/// in string context should return the string

8 views
Skip to first unread message

Stéphane Payrard

unread,
Nov 18, 2003, 12:19:00 PM11/18/03
to perl6-l...@perl.org
s/// in string context should return the string after substituion.
It seems obvious to me but I mention it because I can't find it
in the apocalypses.

--
stef

Austin Hastings

unread,
Nov 18, 2003, 3:04:04 PM11/18/03
to st...@payrard.net, perl6-l...@perl.org
As a "Bvalue" where possible, so they can cascade and nest.

=Austin

Joe Gottman

unread,
Nov 18, 2003, 9:58:21 PM11/18/03
to Perl6
----- Original Message -----
From: "Austin Hastings" <Austin_...@Yahoo.com>
To: <st...@payrard.net>; <perl6-l...@perl.org>
Sent: Tuesday, November 18, 2003 3:04 PM
Subject: [perl] RE: s/// in string context should return the string


> As a "Bvalue" where possible, so they can cascade and nest.

Excuse me. I know enough C++ to know the difference between an lvalue
and an rvalue, but what the heck is a BValue?

Joe Gottman


Piers Cawley

unread,
Nov 19, 2003, 4:18:23 AM11/19/03
to Stéphane Payrard, perl6-l...@perl.org
Stéphane Payrard <st...@payrard.net> writes:

Surely it should return the string after substitution, but with an
appropriate 'but true' or 'but false' property depending on whether
anything was substituted. Though that could have its own problems too.


Piers Cawley

unread,
Nov 19, 2003, 4:16:03 AM11/19/03
to Joe Gottman, Perl6
"Joe Gottman" <jgot...@carolina.rr.com> writes:

A mystery to me.

Austin Hastings

unread,
Nov 19, 2003, 9:03:38 AM11/19/03
to Joe Gottman, Perl6

Something which could be Bound to another rex. Vis (p5):

$x =~ s/foo/bar/ =~ s/moo/goo/;

Might as well make them chainable.

=Austin

Larry Wall

unread,
Nov 19, 2003, 11:36:44 AM11/19/03
to Perl6
On Wed, Nov 19, 2003 at 09:03:38AM -0500, Austin Hastings wrote:
:
:
: > -----Original Message-----

Sigh. There's no =~ operator in Perl 6.

And it's not at all clear that ~~ should be associative. In fact,
it's not at all clear that ~~, a symmetrical operator, should bind
to any kind of mutator (using the term loosely). Operations that
have side effects are inherently asymmetrical and should probably be
bound with . in any event. And that does associate left to right,
though there are no guarantees that the returned value of a method is
the left one. The only mutator operator that currently does that is
"but". So maybe it could be something like:

$x but s/foo/bar/ but s/moo/goo/;

We'd have to make "property" context recognize mutators for that to
work, though. I'm more inclined to make

$x.s/foo/bar/.s/moo/goo/;

work somehow. Basically .s would be a postfix quote macro, or some such.
I'm not sure I want to propose macromethods just yet. The compile-time
vs run-time typing and scoping issues would be hairy.

Having said all that about ~~ vs mutators, I note two interesting
facts-in-waiting:
1) The ~~ operator likes to match using regexes.
2) We've defined any regex to be a potential mutator if it uses <cut>.

Ah, consistency...

Larry

Simon Cozens

unread,
Nov 19, 2003, 1:17:33 PM11/19/03
to perl6-l...@perl.org
la...@wall.org (Larry Wall) writes:
> Sigh. There's no =~ operator in Perl 6.

How should we go about bringing A3 up to match current reality? It is, after
all, over two years old now.

--
End July 2001 - Alpha release for demonstration at TPC

Jonathan Scott Duff

unread,
Nov 19, 2003, 1:25:32 PM11/19/03
to Simon Cozens, perl6-l...@perl.org
On Wed, Nov 19, 2003 at 06:17:33PM +0000, Simon Cozens wrote:
> la...@wall.org (Larry Wall) writes:
> > Sigh. There's no =~ operator in Perl 6.
>
> How should we go about bringing A3 up to match current reality? It is, after
> all, over two years old now.

Isn't Allison the maintainer? Just prod her with an email or two.

-Scott
--
Jonathan Scott Duff
du...@lighthouse.tamucc.edu

Allison Randal

unread,
Nov 19, 2003, 6:39:28 PM11/19/03
to Simon Cozens, perl6-l...@perl.org
Simon wrote:
>
> How should we go about bringing A3 up to match current reality? It is, after
> all, over two years old now.

We talked about this today. Our current thought is to retroactively
write the Synopses and keep those up-to-date (with notes in the outdated
parts of the A's and E's pointing to the relevant section of the
S's).

Allison

Simon Cozens

unread,
Nov 19, 2003, 8:31:52 PM11/19/03
to perl6-l...@perl.org
a...@shadowed.net (Allison Randal) writes:
> We talked about this today. Our current thought is to retroactively
> write the Synopses and keep those up-to-date (with notes in the outdated
> parts of the A's and E's pointing to the relevant section of the
> S's).

To be honest, I don't care how it's actually done, I just want to avoid
having Larry pop up and say "Sheesh, didn't you know X?", where X is
something we've never heard of before and contradicts many things he's
said publically in the past.

--
<blech> lathos: nothing can make up for the middle class dinner
party couple sex ARSE of Sade

Smylers

unread,
Nov 19, 2003, 3:23:30 PM11/19/03
to perl6-l...@perl.org
Piers Cawley writes:

> Stéphane Payrard <st...@payrard.net> writes:
>
> > s/// in string context should return the string after substituion.
>

> Surely it should return the string after substitution, but with an
> appropriate 'but true' or 'but false' property depending on whether
> anything was substituted.

Perl 5 C<s///g> currently returns the number of substitutions made.
This has its uses, so Perl 6 C<s:e///> should probably continue to do
this.

Can we have a return value that stringifies to the result of the
substitution but numifies to the number of substitutions made and
boolifies based on the number rather than the string (to allow for
situations such as a successful substitution producing an empty string)?

Would we want that anyway? It means there's a difference between:

$substituted = $text ~~ s/$pattern/$replacement/;
if $substituted

and:

if $text ~~ s/$pattern/$replacement/

which doesn't sound like a great feature to leave lying around in a
language.

Thinking about this some more, I'm not convinced about Stéphane's claim.
Is it useful to return the substituted string? We already have the
substituted string in one variable (C<s///> doesn't work on a constant), so
what's the point in having it in a second one?

Often I want to modify a string and leave the _original_ behind in a
separate variable:

(my $modified = $original) ~~ s/$pattern/$replacement/;

but that's different, because the two variables end up with
(potentially) different contents rather than always being duplicates.

This, however, is irritating:

my @new = map { s:e/$pattern/$replacement/; $_ } @old;

I forget the C<; $_> far more often than I like to admit and end up with
an array of integers instead of modified strings. So I'd like a more
elegant way of writing that -- but I don't think making the return value
of C<s///> more complicated (and duplicating data in the process) would
be a nett gain.

It seems that the substituted text is needed only either in the original
variable or somewhere else, but not both. A variant of C<s///> which
did not modify the original but did return the modified string could
have some use. That'd allow things such as:

my $modified = $original ~~ ss/$pattern/$replacement/;

my @new = map { ss:e/$pattern/$replacement/ } @old;

except that C<ss///> is obviously a lousy name for such an operator.
I've no idea what a good name would be for distinguishing between
'modify yourself in this way and return how many times you did it' and
'return a copy of yourself modified in this way'; I fear that it'd be
too easy to get these confused and do the wrong thing.[*0]

Having an operator that substitutes and returns the modified string
would certainly have its uses, but unless a way can be found of doing
this which doesn't make other things worse, we'd just be rearranging the
inconveniences and introducing new pitfalls; on balance I think I'd
rather keep the pitfalls that I'm already used to avoiding than fix
those but have to learn about new ones.

[*0] I suppose it could be seen as analogous to the difference
between C<$count + 2> and C<$count += 2>. So maybe that's a precedent
for such distinctions and it wouldn't be that confusing after all
(C<~~> and C<~~=> anybody?). Or maybe the fact that learners often
get those different sorts of addition confused is a reason for not
going any further along this route and making matters worse.

Smylers

Jonathan Scott Duff

unread,
Nov 20, 2003, 9:46:34 AM11/20/03
to Smylers, perl6-l...@perl.org
On Wed, Nov 19, 2003 at 08:23:30PM +0000, Smylers wrote:
> This, however, is irritating:
>
> my @new = map { s:e/$pattern/$replacement/; $_ } @old;
>
> I forget the C<; $_> far more often than I like to admit and end up with
> an array of integers instead of modified strings.

That one gets me every now and then too.

> So I'd like a more elegant way of writing that -- but I don't think
> making the return value of C<s///> more complicated (and duplicating
> data in the process) would be a nett gain.

What if the method form of s/// didn't mutate the string, but returned
the mutated result? Then, you'd just need to do something like:

my @new = map { $_.s:e/$pat/$rep/ } @old

Except I don't know how the method form of s/// would be spelt.

$string.s:e/$pat/$rep/; # . and ~~ are almost the same?
$string.sub($pat,$rep,"each"); # ick.
$string.sub:e($pat,$rep); # hmm.

Luke Palmer

unread,
Nov 20, 2003, 5:19:03 PM11/20/03
to Smylers, perl6-l...@perl.org
Smylers writes:
> Piers Cawley writes:

>
> > St辿phane Payrard <st...@payrard.net> writes:
> >
> > > s/// in string context should return the string after substituion.
> >
> > Surely it should return the string after substitution, but with an
> > appropriate 'but true' or 'but false' property depending on whether
> > anything was substituted.
>
> Perl 5 C<s///g> currently returns the number of substitutions made.
> This has its uses, so Perl 6 C<s:e///> should probably continue to do
> this.
>
> Can we have a return value that stringifies to the result of the
> substitution but numifies to the number of substitutions made and
> boolifies based on the number rather than the string (to allow for
> situations such as a successful substitution producing an empty string)?
>
> Would we want that anyway? It means there's a difference between:
>
> $substituted = $text ~~ s/$pattern/$replacement/;
> if $substituted
>
> and:
>
> if $text ~~ s/$pattern/$replacement/
>
> which doesn't sound like a great feature to leave lying around in a
> language.

Probably wouldn't want that. But returning the text substituted isn't
necessarily a bad idea, especially if it has a C<but true> on it.

As long as there's a way to strip boolifying properties en passant.

$substituted = ($text ~~ s/$pattern/$replacement/) but nothing;

Seems rather authoritative, doesn't it? :-)

What I really want is a functional version of s///. Like:

my $substituted = $text.s(/$pattern/, { $replacement });

Without modifying $text.

Luke

> Thinking about this some more, I'm not convinced about St辿phane's claim.

Piers Cawley

unread,
Nov 21, 2003, 5:51:16 AM11/21/03
to Luke Palmer, Smylers, perl6-l...@perl.org
Luke Palmer <fibo...@babylonia.flatirons.org> writes:

> Smylers writes:
>> Perl 5 C<s///g> currently returns the number of substitutions made.
>> This has its uses, so Perl 6 C<s:e///> should probably continue to do
>> this.
>>
>> Can we have a return value that stringifies to the result of the
>> substitution but numifies to the number of substitutions made and
>> boolifies based on the number rather than the string (to allow for
>> situations such as a successful substitution producing an empty string)?
>>
>> Would we want that anyway? It means there's a difference between:
>>
>> $substituted = $text ~~ s/$pattern/$replacement/;
>> if $substituted
>>
>> and:
>>
>> if $text ~~ s/$pattern/$replacement/
>>
>> which doesn't sound like a great feature to leave lying around in a
>> language.
>
> Probably wouldn't want that. But returning the text substituted isn't
> necessarily a bad idea, especially if it has a C<but true> on it.
>
> As long as there's a way to strip boolifying properties en passant.
>
> $substituted = ($text ~~ s/$pattern/$replacement/) but nothing;
>
> Seems rather authoritative, doesn't it? :-)

Oh! I like that. This would, presumably strip off *all* but related
properties. (Say that aloud to your colleagues and watch their
expressions).

> What I really want is a functional version of s///. Like:
>
> my $substituted = $text.s(/$pattern/, { $replacement });
>
> Without modifying $text.

That would be handy too.

Simon Cozens

unread,
Nov 21, 2003, 6:45:59 AM11/21/03
to perl6-l...@perl.org
fibo...@babylonia.flatirons.org (Luke Palmer) writes:
> $substituted = ($text ~~ s/$pattern/$replacement/) but nothing;

Surely "no buts"? :)

> What I really want is a functional version of s///. Like:
> my $substituted = $text.s(/$pattern/, { $replacement });
> Without modifying $text.

$rubyometer++;

--
FAILURE:
When Your Best Just Isn't Good Enough

http://www.despair.com

A. Pagaltzis

unread,
Nov 21, 2003, 7:14:19 AM11/21/03
to perl6-l...@perl.org
* Smylers <Smy...@stripey.com> [2003-11-20 11:50]:

> This, however, is irritating:
>
> my @new = map { s:e/$pattern/$replacement/; $_ } @old;
>
> I forget the C<; $_> far more often than I like to admit and
> end up with an array of integers instead of modified strings.
> So I'd like a more elegant way of writing that -- but I don't
> think making the return value of C<s///> more complicated (and
> duplicating data in the process) would be a nett gain.

s:e/$pattern/$replacement/ for my @new = @old;

But that without nested for modifiers (will those work?) this
isn't be applicable in the middle of a map map map map chain..

--
Regards,
Aristotle

"If you can't laugh at yourself, you don't take life seriously enough."

A. Pagaltzis

unread,
Nov 21, 2003, 7:21:28 AM11/21/03
to perl6-l...@perl.org
* A. Pagaltzis <paga...@gmx.de> [2003-11-21 13:16]:

> But that without nested for modifiers (will those work?) this
> isn't be applicable in the middle of a map map map map chain..

I shouldn't edit my stuff so heavily.. what a mess.

Piers Cawley

unread,
Nov 21, 2003, 8:26:18 AM11/21/03
to Simon Cozens, perl6-l...@perl.org
Simon Cozens <si...@simon-cozens.org> writes:

> fibo...@babylonia.flatirons.org (Luke Palmer) writes:
>> $substituted = ($text ~~ s/$pattern/$replacement/) but nothing;
>
> Surely "no buts"? :)
>
>> What I really want is a functional version of s///. Like:
>> my $substituted = $text.s(/$pattern/, { $replacement });
>> Without modifying $text.
>
> $rubyometer++;

Only if it goes into the language Simon.

--
Piers

Larry Wall

unread,
Nov 21, 2003, 8:50:24 PM11/21/03
to perl6-l...@perl.org

It would be nice to have a more systematic way of marking mutators--I
freely admit that it's inconsistent to have the default one way for
sort and the other way for s///. I doubt that our solution to the
problem will be identical to Ruby's, but you'll notice the rubyometer
never seems to go back down when it should. Someone should probably
check it for reference counter leaks... :-)

Larry

David Chan

unread,
Nov 22, 2003, 5:16:50 AM11/22/03
to perl6-l...@perl.org
du...@lighthouse.tamucc.edu wrote:
> Smylers wrote:
>> This, however, is irritating:
>>
>> my @new = map { s:e/$pattern/$replacement/; $_ } @old;
>>
>> So I'd like a more elegant way of writing that -- but I don't think
>> making the return value of C<s///> more complicated (and duplicating
>> data in the process) would be a nett gain.

I'd agree - appearing to have the functional behaviour, but actually
trashing the original string as well, sounds like a great way to confuse
people.

> What if the method form of s/// didn't mutate the string, but returned
> the mutated result? Then, you'd just need to do something like:
>
> my @new = map { $_.s:e/$pat/$rep/ } @old
>
> Except I don't know how the method form of s/// would be spelt.
>
> $string.s:e/$pat/$rep/; # . and ~~ are almost the same?
> $string.sub($pat,$rep,"each"); # ick.
> $string.sub:e($pat,$rep); # hmm.

Hmmm. When doing multiple substitutions, it would be nice to avoid a
hard-to-read nested function call which reads backwards, a la python:

return re.sub('>','&gt;',re.sub('<','&lt;',re.sub('&','&amp;',text)))

... but to also avoid multiple statements like this:

my $tmp = $_;
$tmp =~ s/&/&amp;/g;
$tmp =~ s/</&lt;/g;
$tmp =~ s/>/&gt;/g;
return $tmp;

But maybe it'd be useful to have more visual weight than 's' carries:

return $_.s:e/&/&amp;/.s:e/</&lt;/.s:e/>/&gt;/; # line noise?
return $_.sub:e("&","&amp;").sub:e("<","&lt;").sub:e(">,&gt;") # awkward
return $_.sub:e(&)(&amp;).sub:e(<)(&lt;).sub:e(>)(&gt;) # hmmm

But I forget whether we're allowed space by the dot, which could help.

return $_ . s:e/&/&amp;/ . s:e/</&lt;/ . s:e/>/&gt;/; # readabler

--
$_=".--- ..- ... - .- -. --- - .... . .-. .--. . .-. .-.. .... .- -.-.".
" -.- . .-.\n";s!([.-]+) ?!$_=$1;y/-./10/;$_=chr(-1+ord pack"B*","01".0 x(5
-length)."1$_");y/DWYKAQMOCVLSFENU\\IGBHPJXZ[~nfb`_ow{}/a-z0-9/;$_!ge;print

Luke Palmer

unread,
Nov 22, 2003, 9:36:06 AM11/22/03
to David Chan, perl6-l...@perl.org
David Chan writes:
> Hmmm. When doing multiple substitutions, it would be nice to avoid a
> hard-to-read nested function call which reads backwards, a la python:
>
> return re.sub('>','&gt;',re.sub('<','&lt;',re.sub('&','&amp;',text)))
>
> ... but to also avoid multiple statements like this:
>
> my $tmp = $_;
> $tmp =~ s/&/&amp;/g;
> $tmp =~ s/</&lt;/g;
> $tmp =~ s/>/&gt;/g;
> return $tmp;

Well, assuming we have:

method Str::s(Pair $sub) returns Str {...}

We can write:

.s(/&/ => '&amp;')
.s(/\</ => '&lt;')
.s(/\>/ => '&gt;');

But that's not great (not bad, though). But it's been recognized for
awhile that substitutions like these need behavior more like a
generalized "tr":

.s(/&/ => '&amp;',
/\</ => '&lt;',
/\>/ => '&gt;');

Both of these, of course, poses a problem with the scope of $1 et al.,
which can be fixed by:

.s(/ \> (\w+) \< / => { do_stuff(.{1}) })

But that's starting to look pretty convoluted, and pretty unperlish.

> But maybe it'd be useful to have more visual weight than 's' carries:
>
> return $_.s:e/&/&amp;/.s:e/</&lt;/.s:e/>/&gt;/; # line noise?

Only if you write it that way. Most of perl can be line noise if you
want it to.

return .s:e/ & /&amp;/
.s:e/ \< /&lt;/
.s:e/ \> /&gt;/;

Not so different from my first example above, except slightly more
traditional. The fact that it's a method call means we don't have to
use ~~, which is a big win :-)

This still doesn't quite seem right...

> return $_.sub:e("&","&amp;").sub:e("<","&lt;").sub:e(">,&gt;") # awkward
> return $_.sub:e(&)(&amp;).sub:e(<)(&lt;).sub:e(>)(&gt;) # hmmm
>
> But I forget whether we're allowed space by the dot, which could help.
>
> return $_ . s:e/&/&amp;/ . s:e/</&lt;/ . s:e/>/&gt;/; # readabler

Whitespace is allowed before the dot, but not after it. At least that's
the case when you're subscripting; method calls might be a different
story.

Luke

Piers Cawley

unread,
Nov 25, 2003, 1:17:04 PM11/25/03
to Smylers, perl6-l...@perl.org

aString replace: aPattern with: aString.

aString replaceAll: aPattern with: aString.

Except... the second argument isn't strictly a string because it's
evaluated in the match context. Assuming we get a pure functional form
of the substitution operator, then scoping's going to be fun. If you
want a simple form with the signature:

method String::sub( Rule $pattern, String $replacement )

you're almost certainly going to have to implement that as a macro so
you can get at the string before it's interpolated.

Mark J. Reed

unread,
Nov 25, 2003, 1:44:16 PM11/25/03
to perl6-l...@perl.org
On 2003-11-25 at 18:17:04, Piers Cawley wrote:
> aString replace: aPattern with: aString.
>
> aString replaceAll: aPattern with: aString.

Stop! Stop that at once! No small talk; we're here for
serious discussions!

:)

> Except... the second argument isn't strictly a string because it's
> evaluated in the match context. Assuming we get a pure functional form
> of the substitution operator, then scoping's going to be fun. If you
> want a simple form with the signature:
>
> method String::sub( Rule $pattern, String $replacement )
>
> you're almost certainly going to have to implement that as a macro so
> you can get at the string before it's interpolated.

Or you could have the method version take a closure/proc object/block/whatever,
which gets run each time to generate the replacement. Quoting is then
not an issue.

Hm. What was that about the Rubyometer? :)

-Mark
--
Mark REED | CNN Internet Technology
1 CNN Center Rm SW0831G | mark...@cnn.com
Atlanta, GA 30348 USA | +1 404 827 4754

Piers Cawley

unread,
Nov 25, 2003, 2:53:09 PM11/25/03
to Mark J. Reed, perl6-l...@perl.org
"Mark J. Reed" <mark...@turner.com> writes:

> On 2003-11-25 at 18:17:04, Piers Cawley wrote:
>> aString replace: aPattern with: aString.
>>
>> aString replaceAll: aPattern with: aString.
>
> Stop! Stop that at once! No small talk; we're here for
> serious discussions!
>
> :)
>
>> Except... the second argument isn't strictly a string because it's
>> evaluated in the match context. Assuming we get a pure functional form
>> of the substitution operator, then scoping's going to be fun. If you
>> want a simple form with the signature:
>>
>> method String::sub( Rule $pattern, String $replacement )
>>
>> you're almost certainly going to have to implement that as a macro so
>> you can get at the string before it's interpolated.
>
> Or you could have the method version take a closure/proc
> object/block/whatever, which gets run each time to generate the
> replacement. Quoting is then not an issue.

Well, yes, sorry, thought that was implicit. The macro form would
simply replace itself with an appropriate call to the

method String::sub(Rule $pattern, Block &replace_block) {...}

form. This is perl after all, no harm sprinkling a little syntactic
sugar. Catch is, the macro form can't really (safely) look like a
method call because at macro expansion time we don't know the
invocant's type (or even if it is an object).

> Hm. What was that about the Rubyometer? :)

Is that how Ruby does it then?

Mark J. Reed

unread,
Nov 25, 2003, 3:36:35 PM11/25/03
to perl6-l...@perl.org
On 2003-11-25 at 19:53:09, Piers Cawley wrote:
> Is that how Ruby does it then?

=begin RubyDigression

Ruby's String class has the methods sub (replace once) and gsub
(replace all), which leave the invocant alone and return the
result of the substitution, and sub! and gsub!, which modify the
invocant in place. These methods may take as a replacement operand a
string, which may contain the metacharacters '\&', '\1', '\2', etc.
to refer to captured subexpressions in the regular expression match
(and which have to be protected from normal interpolation-context
string processing, e.g. by using a single-quoted string instead of
a double-quoted one). However, instead of passing a replacement
string, you can supply a block which will get executed for each
match, with the captured subexpressions as parameters; this is how
Ruby handles the more complex semantics for which Perl5 substitutions
generally use one or more instances of the /e modifier.

So the Ruby equivalent of this Perl5 code:

$str =~ s/(foo)/$1tball/g;

is either this:

str.gsub!(/(foo)/, '\1tball')

or this:

str.gsub!(/(foo)/) {|old| "#{old}tball"}

It is generally agreed that the parameters to the block are insufficient;
the other useful match result values such as $&, $`, $' are not included,
so the block must use those (global!) variables directly if needed;
this is generally considered Bad Form. For instance, if you remove the
parens from the above, you get this Perl5:

$str =~ s/foo/$&tball/g;

Which sets off the "oh, no, you used $&!" alarm. The Ruby equivalent is
either this:

str.gsub!(/foo/, '\&tball')

or this:

str.gsub!(/foo/) {"#{$&}tball"}

The behavior may change in a future revision of Ruby to instead
pass the entire MatchData object which is normally returned by the
String#match method. str.match(/regex/) is roughly equivalent to Perl5
$str =~ /regex/; the latter syntax also works in Ruby, but instead
of a MatchData object it returns either nil [for no match] or the
character index where the match was found.)

=end RubyDigression

0 new messages