Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

You can't assign $_ to a hash in a foreach statement

by markdibley (Sexton)
on Apr 08, 2022 at 16:33 UTC ( [id://11142845]=perlquestion: print w/replies, xml ) Need Help??

markdibley has asked for the wisdom of the Perl Monks concerning the following question:

I have tried everything I can think of (plus a tonne of random experiments) to assign $_ within the foreach statement to a hash. I know that you can assign it after the foreach line, but I have a very particular code limitation which doesn't allow me to do this.

#!/usr/bin/perl -s use strict; use Data::Dumper; my @x = qw(a c e g); my $var = {'a'=>"z", 'b'=>"y", 'c'=>"x", 'd'=>"w", 'e'=>"v", 'f'=>"u", + 'g'=>"t", 'h'=>"s"}; my $y = "e"; foreach $var->{$y} (@x){ print "$y = $var->{$y}\n"; $y = $var->{$y}; } die Dumper($var);

What I think is happening is the perl compiler cannot handle '{' and '}' characters in the position where it is looking for $VAR to assign $_ to. When I run the code not only do I get an error about the foreach line, but I also get a syntax error about the print line where there is no syntax error.

syntax error at ./foreach2var.pl line 9, near "$var->" syntax error at ./foreach2var.pl line 12, near "}" Execution of ./foreach2var.pl aborted due to compilation errors.

Is there any way to assign $_ within the foreach statement directly to a hash reference rather than assigning it with $var->{$y} = $_; on the following line?

I am looking for the following output

e = a a = c c = e e = g $VAR1 = { 'e' => 'g', 'a' => 'c', 'd' => 'w', 'c' => 'e', 'h' => 's', 'b' => 'y', 'g' => 't', 'f' => 'u' };

Also, I am aware that the following works, but again, I have a particular code limitation which means I have to be able to handle foreach statements

#!/usr/bin/perl -s use strict; use Data::Dumper; my @x = qw(a c e g); my $var = {'a'=>"z", 'b'=>"y", 'c'=>"x", 'd'=>"w", 'e'=>"v", 'f'=>"u", + 'g'=>"t", 'h'=>"s"}; my $y = "e"; while($var->{$y} = shift @x){ print "$y = $var->{$y}\n"; $y = $var->{$y}; } die Dumper($var);

Replies are listed 'Best First'.
Re: You can't assign $_ to a hash in a foreach statement
by ikegami (Patriarch) on Apr 08, 2022 at 16:49 UTC

    No.

    For starters, a foreach loop never assigns to the variable. It makes it an alias to the value for that iteration.

    And even if it did assign, the original value is restored at the end of the loop, so it would be of no use to you.

    $_ = "abc"; say; for (qw( def ghi )) { say; } say;

    Output:

    abc def ghi abc

      You are right about the scope and actually for my purposes it is not necessary. I shouldn't have included the die at the end as it's output and the modified hash structure is not required. Sorry.

      perldoc says "The foreach loop iterates over a normal list value and sets the scalar variable VAR to be each element of the list in turn." So I was expecting to be able to use a hash reference as VAR. It doesn't mention aliasing. But as you say, the answer does appear to be No.

        perldoc says "The foreach loop iterates over a normal list value and sets the scalar variable VAR

        $var->{$y} isn't a variable.


        the modified hash structure is not required

        Did you just say it's not necessary to change $var->{$y}? Then why do you do it?


        t doesn't mention aliasing.

        Maybe, but it does mention the variable acts as an alias.

        If any element of LIST is an lvalue, you can modify it by modifying VAR inside the loop. Conversely, if any element of LIST is NOT an lvalue, any attempt to modify that element will fail.

Re: You can't assign $_ to a hash in a foreach statement
by cavac (Parson) on Apr 11, 2022 at 07:01 UTC

    On a sidenote, using the implicit $_ variable make your code harder to read and harder to maintain. You have to consider every statement carefully and think about if it has the side effect of changing or using $_. This can be especially time consuming if you change the code sometime in the future and it suddenly breaks.

    If you always use names variables, it makes it much easier to follow the data flow and see what is assigned to what variable.

    perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
Re: You can't assign $_ to a hash in a foreach statement
by k-mx (Scribe) on Apr 15, 2022 at 11:24 UTC

    Maybe hash slice?

    #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; my %h = (a => 0, b => 0, c => 0); my @ar = ( 42, 43 ); @h{ qw( a c ) } = @ar; print Dumper \%h;
Re: You can't assign $_ to a hash in a foreach statement
by Anonymous Monk on Apr 08, 2022 at 19:11 UTC
    I have a particular code limitation

    explain plz

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11142845]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (5)
As of 2024-04-19 10:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found