Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re^4: Have you netted a Perl Monk or Perl Pretender in 5 minutes or less?

by Anonymous Monk
on Sep 15, 2005 at 15:27 UTC ( #492281=note: print w/replies, xml ) Need Help??


in reply to Re^3: Have you netted a Perl Monk or Perl Pretender in 5 minutes or less?
in thread Have you netted a Perl Monk or Perl Pretender in 5 minutes or less?

Um. This is really a serious question. Is there something useful that example accomplishes, or is it just trying to point out a Perl anonomly (some might call it broken behavior)?
#!/usr/bin/perl -w use strict; our $c = 2; print "Before: c=$c\n"; my $c = 1 unless $c; print "After: c=$c\n";
  • Comment on Re^4: Have you netted a Perl Monk or Perl Pretender in 5 minutes or less?
  • Download Code

Replies are listed 'Best First'.
Re^5: Have you netted a Perl Monk or Perl Pretender in 5 minutes or less?
by QM (Parson) on Sep 15, 2005 at 18:22 UTC
    #!/usr/bin/perl -w use strict; our $c = 2; print "Before: c=$c\n"; my $c = 1 unless $c; print "After: c=$c\n";
    This highlights the duality of my.

    If you had actually run that, you should have got the compiler error:

    "my" variable $c masks earlier declaration in same scope at 492281.pl +line 6.
    because you had warnings on.

    Let's do it line by line:

    our $c = 2;
    The global variable also known as $main::$c is formally declared (for strictness), and assigned the value 2.
    print "Before: c=$c\n";
    The value of $main::$c (2) is printed.
    my $c = 1 unless $c;
    If the current $c variable is true, declare a lexical variable with the same name, and assign it the value 1. On the first (and here only) pass, $c is just shorthand for the global $main::$c, and it's value is 2, so the lexical assignment doesn't happen.

    However, the lexical creation did! Until the lexical $c goes out of scope (in this case, at the end of the file), all instances of $c refer to this lexical variable, and not to the global $main::$c. To access $main::$c, the "long" name must be used, as the short name points to something different.

    print "After: c=$c\n";
    The value of the lexical $c is printed. However, since the assignment didn't happen, it's still undefined. And if you'd actually tried it, you would have seen this:
    Use of uninitialized value in concatenation (.) or string at 492281.pl + line 7.
    just before the "After..." string was printed.

    To separate these issues, try changing my $c to my $d:

    #!/usr/bin/perl -w use strict; our $c = 2; print "Before: c=$c\n"; my $d = 1 unless $c; print "After: d=$d\n";
    gives
    Before: c=2 Use of uninitialized value in concatenation (.) or string at 492281.pl + line 7. After: d=
    Do you see why?

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

      So are we admitting that this is a poor interview question? And bad design on the part of Perl in regards to statement modifiers? Compare...
      #!/usr/bin/perl -w use strict; our $c = 2; print "Before: c=$c\n"; unless($c){my $c = 1} print "After: c=$c\n";
        So are we admitting that this is a poor interview question?
        This behavior of my is a fact. Precisely because of this fact, it's a good interview question. Knowing where the cracks in the armor lie is just as important as wearing the armor in the first place.

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

Re^5: Have you netted a Perl Monk or Perl Pretender in 5 minutes or less?
by benrwebb (Scribe) on Sep 29, 2005 at 05:24 UTC
    It tests the candidate's understanding of Perl syntax. To understand that line you must know the effects of using unless (and if I'm asking the questions that will quickly turn into what Perl considers true and false values) as well as execution order in a statement. Put concicely, it says that if $c exists and is true maintain it's value, otherwise set it to 1. It is an occasionally useful construct for fixing user input errors and the like.

    I did notice that the way you've got it written it is a trick question - if you set the original value of $c to be 0 or "" the "my" would produce a warning about re-declaring a variable that was declared in the same scope.
      To understand that line you must know the effects of using unless (and if I'm asking the questions that will quickly turn into what Perl considers true and false values) as well as execution order in a statement. Put concicely, it says that if $c exists and is true maintain it's value, otherwise set it to 1.
      Wrong. It is an anomoly caused by the interaction between lexical scopes created by "my" and postfix conditionals. To put it correctly, if $c is false, then set it to one. If $c is true then set it to undef. If you actually try running that snippet you'll learn what it really does.
        Correct you are, my bad. I'm used to calling that in a different context so I looked back at the code I had actually been using. This is what would actually work the way I described:
        use strict; use warnings; my $c = 1; my $d = undef; sub sbr { $c = 2 unless $c; print "c = $c\n"; $d = 4 unless $d; print "d = $d\n"; } sbr();


        Thanks for correcting my mistake

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://492281]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (6)
As of 2020-02-28 10:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What numbers are you going to focus on primarily in 2020?










    Results (123 votes). Check out past polls.

    Notices?