Clever implementation for s///r

T

Tim McDaniel

So I read that Perl 5.14 (and maybe earlier?) has this nice feature
s///r:

If the /r (non-destructive) option is used then it runs the
substitution on a copy of the string and instead of returning the
number of substitutions, it returns the copy whether or not a
substitution occurred. The original string is never changed when
/r is used. The copy will always be a plain string, even if the
input is an object or a tied variable.

and similarly for tr///r.

So I gather that

my @newargs = map { split ' ', tr/;,/ /r } @_;

would split each element of @_ at semicolon/comma/whitespace (multiple
delimiters in a row are the same as one, leading/trailing delimiters
are ignored), but not change @_.

Alas that I have Perl 5.8.8 at one place, and it knoweth not s///r and
tr///r. Is there any clever way to implement it? I can see no
way other than to declare a variable and assign to it, like

my @t = @_;
my @newargs = map { tr/;,/ /; split } @t;

or

my @newargs = map { my $t = $_; $t =~ tr/;,/ /; split(' ', $t) } @_;

or even -- Lord forfend --

my @newargs = map { local $_ = $_; tr/;,/ /; split } @_;

none of which are as nice (and that last, while legal, would probably
make my cow-orkers break out in hives and bring out pitchforks. Note
that "my $_" wasn't possible in 5.8.8).

Is there an efficient decent way to produce a copy of an array like @_
and break the magic link back to the original? I ask because I had
been thinking that one way to do it would be if
(@_)
or
+@_
would produce a temp copy of @_, but they don't. And
reverse reverse @_
is just too cutesy.
 
R

Rainer Weikusat

So I read that Perl 5.14 (and maybe earlier?) has this nice feature
s///r:

If the /r (non-destructive) option is used then it runs the
substitution on a copy of the string and instead of returning the
number of substitutions, it returns the copy whether or not a
substitution occurred. The original string is never changed when
/r is used. The copy will always be a plain string, even if the
input is an object or a tied variable.

and similarly for tr///r.

So I gather that

my @newargs = map { split ' ', tr/;,/ /r } @_;

would split each element of @_ at semicolon/comma/whitespace (multiple
delimiters in a row are the same as one, leading/trailing delimiters
are ignored), but not change @_.

Alas that I have Perl 5.8.8 at one place, and it knoweth not s///r and
tr///r. Is there any clever way to implement it? I can see no
way other than to declare a variable and assign to it

The obvious other idea would be to use a function:

sub cpy { return @_; }
 
T

Tim McDaniel

The obvious other idea would be to use a function:
sub cpy { return @_; }

That does file off the specialness. Thanks! My test was (in a
different test, not the example purpose what I was asking about)

my @bpbpbp = map { s/^/f/; $_ } sub{@_}->(@a);
 
J

jl_post

Alas that I have Perl 5.8.8 at one place, and it knoweth not s///r and
tr///r.  Is there any clever way to implement it?  I can see no
way other than to declare a variable and assign to it, like

    my @t = @_;
    my @newargs = map { tr/;,/ /; split } @t;


How about:

my @newargs = map { tr/;,/ /; split } @{ [@_] };

Would this work for you?

-- Jean-Luc
 
C

C.DeRykus

So I read that Perl 5.14 (and maybe earlier?) has this nice feature
s///r:

If the /r (non-destructive) option is used then it runs the
substitution on a copy of the string and instead of returning the
number of substitutions, it returns the copy whether or not a
substitution occurred. The original string is never changed when
/r is used. The copy will always be a plain string, even if the
input is an object or a tied variable.

and similarly for tr///r.

So I gather that

my @newargs = map { split ' ', tr/;,/ /r } @_;

would split each element of @_ at semicolon/comma/whitespace (multiple
delimiters in a row are the same as one, leading/trailing delimiters
are ignored), but not change @_.

Alas that I have Perl 5.8.8 at one place, and it knoweth not s///r and
tr///r. Is there any clever way to implement it? I can see no
way other than to declare a variable and assign to it, like

my @t = @_;
my @newargs = map { tr/;,/ /; split } @t;

or

my @newargs = map { my $t = $_; $t =~ tr/;,/ /; split(' ', $t) } @_;

or even -- Lord forfend --

my @newargs = map { local $_ = $_; tr/;,/ /; split } @_;

none of which are as nice (and that last, while legal, would probably
make my cow-orkers break out in hives and bring out pitchforks. Note
that "my $_" wasn't possible in 5.8.8).

Is there an efficient decent way to produce a copy of an array like @_
and break the magic link back to the original? I ask because I had
been thinking that one way to do it would be if
(@_)
or
+@_
would produce a temp copy of @_, but they don't. And
reverse reverse @_
is just too cutesy.

my @newargs = map { tr/;,/ /; split } qq{@_}

Still cute and probably dodgy but brief :)
 
T

Tim McDaniel

my @newargs = map { tr/;,/ /; split } qq{@_}

Still cute and probably dodgy but brief :)

I've never before reacted to a comp.lang.perl.* posting with LOLing!

Yeah, dodgy -- it depends on $" alias $LIST_SEPARATOR being a space
(the default) or at worst ;,space. But if you guarantee that, and you
REALLY shouldn't be changing it globally anyway, Bob's your uncle.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top