Sometimes the the implicit aliasing of $_ produces unwanted side effects

e.g in the following code to strip the character "h" from all elements in @arr

my @bla = map { tr/h//d; $_ } @arr;

will also change the entries of @arr.

To avoid this, one needs to write

 my @bla = map { (my $tmp = $_) =~ tr/h//d; $tmp } @arr;

or

my @bla=@arr; tr/h//d for @bla;

Hmm ... I'm wondering if it would make sense to have an alternative non-aliased special var, maybe like $__ such that one could write:

my @bla = map { $__=~tr/h//d; $__ } @arr;

well still not really DRY ...

Any alternative ideas?

Cheers Rolf

UPDATE: alternatively map {tr/h//d; $_} map {$_} @arr

Replies are listed 'Best First'.
Re: non aliased default var $_
by JavaFan (Canon) on Mar 10, 2010 at 13:36 UTC
    I've been using the following for over a decade:
    my @bla = map {my $_ = $_; tr/h//d; $_} @arr;
    Of course, on older Perls, the 'my' was spelled 'local'.
      Thanx, my $_ = $_; is really a good idiom!

      In this example with map it might look complicated, because we have to define a return value...

      ...but in a for loop it's easy to spot, understand and handy to use.

      Perfect! :)

      Cheers Rolf

        is really a good idiom!

        For modern perl (5.10+)

Re: non aliased default var $_
by jwkrahn (Abbot) on Mar 10, 2010 at 16:14 UTC
    my @bla=@arr; tr/h//d for @bla;

    Which could also be written as:

    tr/h//d for my @bla = @arr;
Re: non aliased default var $_
by ikegami (Patriarch) on Mar 10, 2010 at 15:51 UTC

    That won't work. How would map know to use $__ instead of the normal result. You'd need a different function. Two such functions already exist: List::MoreUtils's apply and Algorithm::Loops's Filter.

    use List::MoreUtils qw( apply ); my @bla = apply { tr/h//d } @arr; use Algorithm::Loops qw( Filter ); my @bla = Filter { tr/h//d } @arr;
      yeah I already realized that $__ wouldn't help a lot ...

      > Two such functions already exist...

      Thx! :)

      Cheers Rolf

      PS: but I have to admit that the documentation for Algorithm::Loops is too complicated for me...

Re: non aliased default var $_
by BrowserUk (Patriarch) on Mar 10, 2010 at 12:16 UTC
      my @bla = map{ tr/h//d; $_ } @{\@arr};

      Your @{\...} does nothing. You surely meant

      my @bla = map{ tr/h//d; $_ } @{[@arr]}; # ^ ^

      - tye        

        You surely meant

        You're correct.

      > my @bla = @arr; tr/h//d for @bla;

      already mentioned in the OP

      > my @bla = map{ tr/h//d; $_ } @{\@arr};¹

      that's a nice one! 8)

      But maybe my (updated) alternative is easier to read (?):

      my @bla = map{ tr/h//d; $_ } map {$_} @arr;

      Cheers Rolf

      UPDATE: ¹) as tye pointed out it should be @{ [@arr] }

        > my @bla = @arr; tr/h//d for @bla;

        already mentioned in the OP

        Sorry. I missed that. But then, that makes me wonder why you are seeking an alternative to it?

        From my perspective, it's a no brainer. On my system, the first alternative runs in 1/64th of the time and uses half the memory to your double map solution;

        C:\test>perl -MTime::HiRes=time -wE"my @a= 0..1e6; my $t= time;my @bla= @a; tr[0][]d for @bla; say tim +e-$t; <>" 0.488373041152954 C:\test>perl -MTime::HiRes=time -wE"my @a= 0..1e6;my $t= time;my @bla= map{tr/h//d; $_}map{$_} @a;say +time-$t; <>" 32.5820000171661

        I realise that you may not work with million element arrays very often, but getting into good habits will save you grief when you are. And it just so much clearer.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.