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

The following gives me "Global symbol "$x" requires explicit package name...":
if (my $x = f() and g($x)) { ... }
Is there a slick way to express this? I want the $x in g($x) to reference the lexical $x on the same line.

Replies are listed 'Best First'.
Re: scope of my $x in if statements
by ikegami (Patriarch) on May 07, 2009 at 20:50 UTC

    I want the $x in g($x) to reference the lexical $x on the same line.

    That's currently not possible in order to allow

    my $x = $x; # Initialize with value from outer scope.

    The clearest alternative is probably

    my $x = f(); if ($x and g($x)) { ... }
    or
    if (my $x = f()) { if (g($x)) { ... } }

      The first expands the scope of $x.

        So?

Re: scope of my $x in if statements
by FunkyMonk (Bishop) on May 07, 2009 at 21:00 UTC

      Speaking of hideous, the functional approach written in Perl:

      if (my $x = x(f(), \&g)) { ... }
      having defined x() as
      sub x { my ($x, $g) = @_; $x && $g->($x) }

      not either, because the scope of $x is confined to the do block:

      use strict; use warnings; sub f{0} sub g{1} if (do {my $x = f(); $x and g($x)}) { print "cheerful: $x\n"; } __END__ Global symbol "$x" requires explicit package name at scope.pl line 6.
        if (my $x = do {my $x = f(); $x and g($x)}) { print "cheerful: $x\n"; }
Re: scope of my $x in if statements
by moritz (Cardinal) on May 07, 2009 at 20:36 UTC
    I don't think this works in Perl 5, the variable is only visible in the statement after the declaration. It works in Perl 6, though:
    $ perl6 -e 'sub f { 3 }; sub g($a) { $a }; if my $x = f() and g($x) { +say "works" }' works
Re: scope of my $x in if statements
by mikeraz (Friar) on May 07, 2009 at 20:35 UTC

    Setting aside why you want to do this, how about:

    #!/usr/bin/env perl use strict; sub f { return 2; } sub g { my ($y) = shift @_; return $y*2; } if ( my $k = g(my $x = f()) ) { print "If the answer is four I'm happy. Answer == $k\n"; }
    That example seems to do all that you want.
    update: Test platform was perl v5.8.6


    Be Appropriate && Follow Your Curiosity
      That's not equivalent. It can have a different result when f() returns something false

        Meaning if f() returns false and g(falsehood) returns true.
        Time to go work on my test case skills.


        Be Appropriate && Follow Your Curiosity
Re: scope of my $x in if statements
by NetWallah (Canon) on May 07, 2009 at 21:50 UTC
    How about this readable alternative ? :
    if( my $x = $_ = f() and g($_) ) {....}
    and if you REALLY need to modify $x inside g():
    if($_ = \(my $x = f()) and $$_ and g($$_) )
    Update: While I agree with ikegami's assessment below that this is not good practice, I maintain that this IS a solution to the problem posted by the O.P.

         ..to maintain is to slowly feel your soul, sanity and sentience ebb away as you become one with the Evil.

      Clobbering your caller's $_ is bad (even in everyday scenarios), so you need to add local. When you do, you end up with the same problem and nothing is solved.
Re: scope of my $x in if statements
by ig (Vicar) on May 08, 2009 at 01:38 UTC

    I would probably do this as (or as nested if's as ikegami suggested):

    { my $x; if( $x = f() and g($x) ) { ... } }

    If you really didn't like the extra block/indent, you could also do:

    { last unless( my $x = f() ); last unless( g($x) ); ... }