tags:

views:

147

answers:

5

Is there a better way to use tr/// on each element in an array than the following:

foreach (@list) {
    tr/abc/xyz/;
}

I'm playing around with some stuff and I just can't get it out of my head that it doesn't look quite right/optimal. Maybe I'm just thinking of how conditionals can be used in a suffix form. Anyone know if there's a way to use the suffix form for tr/// or s///?

+7  A: 

Are you looking for:

tr/abc/xyz/ foreach (@list);

which basically works the same way as your code (each element of @list is aliased to $_). In this case, you only get to meet Tim Toady and his fraternal twin Tom.

outis
You could elide the parentheses too.
Tordek
I tried that way, but it didn't work for me last night, which is why I posted the question. Now that I've had some sleep, I could actually figure out what the error message meant. I had a C-style comment in there and that's what was freaking it out. It thought the slashes were another operator.Sorry for wasting everyone's time with this one.s/me/the sleep-deprived noob/;
David
No worries. It's amazing how much difference a little sleep (and food) can make.
outis
+4  A: 

tr/abc/xyz/ for (@list); works for me.

William Pursell
+4  A: 

Who uses parentheses with for used as a statement modifier?

tr/abc/xyz/ for @list;

And, if you are golfing, you can save one more character by using y instead of tr.

Sinan Ünür
... and save 2 more without the whitespace: y/abc/xyz/for@list;
toolic
A: 

I'm not a huge fan of for as a statement modifier; not sure why, as there's nothing wrong with it, it just doesn't speak to me in that natural language way that other statement modifiers do. Because of that, I'd use map instead:

map(tr/abc/xyz/, @list);

Purely a matter of preference, and I post it here as an example only. The other answers are fine, too.

Joe Casadonte
The purpose of map is to return something. Map in void context is not considered "best practice."
runrig
On recent Perls however, it does not create a temporary array and is effectively replaced with a for loop. I'd argue that using an expression instead of a block for map is worse!
rjh
@rjh: I'm not sure what you mean with the second sentence. Can you explain, please? I always like to learn more -- thanks!
Joe Casadonte
@Joe: it's subjective, but I'd recommend putting braces around the code in map/grep statements. Ex: map { tr/abc/xyz } @list; It's more consistent with other functions (sort, List::Util/MoreUtils), more readable (especially for more complex code) and makes the scope of $_ more explicit. I also find it weird that map somehow gets this magical ability to accept expressions as arguments when nothing else can (then again, this is Perl) ... OTOH plenty of people don't care either way. A good discussion: http://www.perlmonks.org/?node_id=606931
rjh
Got it -- thanks!
Joe Casadonte
A: 

If you want it as an expression, then I prefer (expression starts at map).

my @trlist = map { tr/abc/xyz/; $_ } @list;

But the foreach variety is probably the simplest way when you just want to change the items in the list:

tr/abc/xyz/ foreach @list;
Axeman
This doesn't do what you expect, when you iterate /over/ an array, $_ is the reference to the element. In other words, in this example @list is still transliterated, but a copy is assigned to @trlist. It is slower, takes more memory and has 0 gain.
Evan Carroll
@EvanCarroll:It does do what I expect. And it performs as an *expression*, just like I said it did.
Axeman