http://www.perlmonks.org?node_id=11119547


in reply to Learning Programming, desperately need to know what information is contained in scalar variables

If $alice and $bob were not assigned values, they are undef. Unlike a language such as C where using a variable that has never been assigned can result in undefined behavior, in Perl the behavior is predictable, and documented. undef is treated like an out-of-band value; it's neither a string nor a number, it's just undef. The undef value has several features:

Here are some examples:

use strict; use warnings; use Devel::Peek; { my $foo; print '$foo is ', (defined($foo) ? 'defined' : 'undef'), "\n"; Dump($foo); } print "\n\n"; { my $foo; print '$foo eq $foo: $foo is stringwise ', ($foo eq $foo ? 'equal' + : 'unequal'), "\n"; Dump($foo); } print "\n\n"; { my $foo; print '$foo == $foo: $foo is numerically ', ($foo == $foo ? 'equal +' : 'unequal'), "\n"; Dump($foo); }

The output will look like this:

$foo is undef SV = NULL(0x0) at 0x1275f40 REFCNT = 1 FLAGS = () Use of uninitialized value $foo in string eq at mytest.pl line 17. Use of uninitialized value $foo in string eq at mytest.pl line 17. $foo eq $foo: $foo is stringwise equal SV = PV(0x1252e70) at 0x12a0470 REFCNT = 1 FLAGS = () PV = 0 Use of uninitialized value $foo in numeric eq (==) at mytest.pl line 2 +4. Use of uninitialized value $foo in numeric eq (==) at mytest.pl line 2 +4. $foo == $foo: $foo is numerically equal SV = PVNV(0x12510f0) at 0x12a0608 REFCNT = 1 FLAGS = () IV = 0 NV = 0 PV = 0

The first block tests for definedness, and then shows what's inside the scalar. Essentially it's empty, just contains undef.

The second block tests the scalar for string equality. This will cause a PV (string value) to be added to the scalar's internal structure, but the PV is =; it's empty. A future test for definedness would still be true. Perl happily just treated undef values as empty strings and compared them. Notice that warnings were generated.

The third block tests the scalar for numeric equality. This has caused an IV and NV (integer and numeric value) field to show up in the scalar struct. They are also empty. The PV field showed up again too, and is also empty. The scalar will still report to be undef if tested with defined. But internally its structure has been altered a little. Notice the warnings again, for doing a numeric comparison on uninitialized value.

All this is hidden in the internals. Mostly you just have to keep in mind that if it hasn't been initialized it will be undef, and that Perl is willing to let you do string and numeric operations and comparisons on undef, upgrading to the appropriate datatype as needed.


Dave

  • Comment on Re: Learning Programming, desperately need to know what information is contained in scalar variables
  • Select or Download Code

Replies are listed 'Best First'.
Re^2: Learning Programming, desperately need to know what information is contained in scalar variables
by Anonymous Monk on Jul 20, 2020 at 21:10 UTC
    I have the book Learning Perl in it there's a section called "Using Scalar-Producing Expressions in List Context" then it goes on to say "Going this direction is straightforward: if an expression doesn't normally have a list value, the scalar value is automatically promoted to make a one-element list:
    @fred = 6 * 7; #gets the one-element list (42) @barney = "hello" . '' . "world";
    In the first example, the array @fred on the left hand side of the operator = makes it a list context, did i got it right? In the second example, "hello" . '' . "world; alone is a scalar expression? Is the array @barney on the left hand side of the operator making it into list context like the first example?
      Yes

      @something = ... ;

      or

      (...) = ... ;

      Are "list assignments".

      The RHS (right hand side) is in list context and the resulting list will be unpacked into the LHS.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

      FIX EDIT: Is the array @barney on the left hand side of the operator = making it into list context like the first example?
        Yes
Re^2: Learning Programming, desperately need to know what information is contained in scalar variables
by Anonymous Monk on Jul 20, 2020 at 15:50 UTC
    That's awesome, thank you very much Dave. I have another question about this piece of code say "Catastrophic crypto fail!" if $alice eq $bob; what value is the expression $alice eq $bob producing?
        So it's returning true because both $alice and $bob are undef?
      «...awesome...»

      Sure. It is the canonical answer. But now comes practice. Which is just another word for repetition. Remember: «No Intuition Without Repetition» (Dr Wisenheimer)

      «The Crux of the Biscuit is the Apostrophe»

      perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

      The expression $alice eq $bob is returning true because both $alice and $bob are undef, that's both contain the same information hence they are equal. Am I right?

        Perl's operators are monomorphic, and its data is polymorphic. Look at this:

        print "Yes\n" if 1 == "1"; # Yes print "Yes\n" if "0" eq 0; # Yes

        In the first test, the number 1 is compared numerically to the string "1". Perl converts that string to a number using rules defined in perldata, and perlop.

        In the second test, the string "0" is compared to the number 0 using stringwise comparison. So the number 0 is promoted to a string for the comparison.

        If you compare undef to undef numerically, undef is treated as 0. If you compare undef to undef stringwise, undef is treated as empty string. So undef == undef produces the same result (true) as 0 == 0. And undef eq undef produces the same value (a Boolean true value) as '' eq '' (empty string is equal to empty string).

        To put it even more plainly:

        • '' eq '' # true: Empty string is equal to empty string.
        • undef, when treated as a string acts like an empty string.
        • The eq operator treats its operands like strings.
        • If $foo and $bar are undef, then $foo eq $foo becomes an empty string to empty string comparison.

        Dave