Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Two meanings of undef

by likbez (Sexton)
on Aug 15, 2020 at 18:21 UTC ( [id://11120786]=perlquestion: print w/replies, xml ) Need Help??

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

The system function undef can be used on the right side of split function or array assignment to skip values that you do not need. For example:

$current_time='14:30:05'
(undef, $min, $sec)=$current_time

In this role it is similar to /dev/null in Unix.

But if used on the right side this function deletes the variable from the symbol table, For example

$line=undef; say "Does not exists" unless(defined($line));

Is this correct understanding?

Edited:

A clarification:

In FAT if you delete a file from the directory it is still present but marked as deleted.

So the fact that that the item still present in symbol table but has a special value does not change the fact that semantically it is deleted and its memory can be now reused.

In other words, if the item in a Perl symbol table has value undef for all practical purposes is it that same as deleted item in FAT and should be treated by interpreter developers in the same way as "not found" item. Implementation is is not flawless though. With the use warnings statement "uninitialized value" warnings are not produced for operations like $i+4 or $i++:

[0]  # cat undef_test.pl
#!usr/bin/perl
use warnings;
use strict;
my ($i,$l,$m);
my $j=$i;
my $k=$l++;
print "m=$m;j=$j,k=$k\n";

[0]  # perl  undef_test.pl
Use of uninitialized value $m in concatenation (.) or string at undef_test.pl line 7.
Use of uninitialized value $j in concatenation (.) or string at undef_test.pl line 7.
m=;j=,k=0

NOTE:

I think undef is not a value, as many here assume, but a function, So
$X=undef;
actually means in Perl:
$X=undef();
and is equivalent to
undef $X;

Replies are listed 'Best First'.
Re: Two meanings of undef (updated)
by haukex (Archbishop) on Aug 15, 2020 at 19:10 UTC
    But if used on the right side this function deletes the variable from the symbol table

    No, that's not quite correct. An uninitalized variable such as my $x; is initially undef, and saying either $x=undef; or undef $x; will return it back to this state of being "undefined" (holding no value). This has nothing to do with the symbol table, it remains unaffected by the value assigned to the variable; and undef is just a special value that a variable can hold. (Update: I should be a bit more specific and say "scalar" instead of "variable". Arrays and hashes are different from scalars.)

    undef is indeed a bit special in the left side of a list assignment, in that it acts as a placeholder there, as you showed.

    Update 2: I responded to your edit here.

    Update 3: Responding to your further edits:

    I think undef is not a value, as many here assume, but a function

    No, in a sense it is both.

Re: Two meanings of undef (updated)
by AnomalousMonk (Archbishop) on Aug 15, 2020 at 20:50 UTC
    ... undef can be used on the right side of split function or array assignment to skip values that you do not need.

    Just to be clear, undef can be used on the left side of list assignment to skip values that you do not need. (Update: Actually, the last | second paragraph of haukex's reply covers this point.)

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my $current_time = '14:30:05'; my @ra = my (undef, $min, $sec) = split ':', $current_time; print qq{'$min' '$sec'}; dd \@ra; " '30' '05' [14, 30, "05"]

    Update: Example code above works the same if the perhaps-a-trifle-obscure
        my @ra = my (undef, $min, $sec) = split ':', $current_time;
    statement is replaced with the more conventional
        my ($min, $sec);
        my @ra = (undef, $min, $sec) = split ':', $current_time;
    (update: or if array assignment is done first
        ... = my @ra = split ':', $current_time;)


    Give a man a fish:  <%-{-{-{-<

Re: Two meanings of undef
by davido (Cardinal) on Aug 16, 2020 at 03:04 UTC

    #!/usr/bin/env perl use strict; use warnings; print "Before assignment: \$xyz ", (exists($::{'xyz'}) ? 'exists' : 'd +oes not exist'), "\n"; eval '$main::xyz = 42;'; print "After assignment: \$xyz ", (exists($::{'xyz'}) ? 'exists' : 'do +es not exist'), "\n"; eval 'print $main::xyz, "\n";'; # Prints 42. eval 'undef $main::xyz;'; print "After undef: \$xyz ", (exists($::{'xyz'}) ? 'exists' : 'does no +t exist'), "\n";

    This produces:

    Before assignment: $xyz does not exist After assignment: $xyz exists 42 After undef: $xyz exists

    The reason I used string eval is because if Perl catches wind of $xyz in the source code it already will populate the symbol table. By using eval I'm able to defer Perl's knowledge of it until just in time.

    The point is that undef $xyz; doesn't remove the entry from the symbol table. Presumably you could do it manually: delete $::{'xyz'};, but you'll also obliterate any other entities that share the same symbol. Possible candidates include a hash, an array, a filehandle, or code, if any exist in the same namespace by the same name.


    Dave

Re: Two meanings of undef
by tobyink (Canon) on Aug 15, 2020 at 21:03 UTC

    Assigning undef to something doesn't remove it from the symbol table.

    perl -MData::Dumper -e'$Foo::somevar = undef; print Dumper \%Foo::'
Re: Two meanings of undef
by LanX (Saint) on Aug 15, 2020 at 19:45 UTC
    > But if used on the right side this function deletes the variable from the symbol table

    That's wrong, the variable is still in the symbol table, it's value is just undef.

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

      That's wrong, the variable is still in the symbol table, it's value is just undef.
      Do not shoot the piano player, ... :-)

      In FAT if you delete a file from the directory it is still present but marked as deleted.

      So the fact that it is still present does not change the fact that semantically it is deleted.

      In other words, if the item in a Perl symbol table has value undef for all practical purposes is it that same as deleted item in FAT and should be treated by interpreter developers in the same way as "not found" item.

        In FAT if you delete item from the directory it is still present but marked as deleted.

        So the fact that it is still present does not change the fact that semantically it is deleted.

        Further to stevieb's and haukex's comments:   In a file system, if you delete a file and then create another file with the same name, do you get any warning that the old file still, in any sense, "exists", or "masks" anything, or that there is any possible symbol/name collision? The symbol spaces of Perl are not file systems.

        c:\@Work\Perl\monks>perl -wMstrict -le "my $scalar = 42; undef $scalar; my $scalar; " "my" variable $scalar masks earlier declaration in same scope ...
        Of course, this message is only emitted if warnings are enabled, but it highlights the fact that an undef-ed scalar still very much exists. (Same behavior with our package-global scalars.)

        I think the critical point that you miss is that undef is a very well-defined value! It is not random, it can be tested, scalars having that value exist in every sense, etc.


        Give a man a fish:  <%-{-{-{-<

        In other words, if the item in a Perl symbol table has value undef for all practical purposes is it that same as deleted item in FAT and should be treated by interpreter developers in the same way as "not found" item.

        No, that's an incorrect analogy. Assigning undef to a scalar is like truncating a file down to zero bytes - it still exists as before, just its content has been cleared. (Not to mention that lexicals aren't even in the symbol table. See perlmod for the details.)

        "In other words, if the item in a Perl symbol table has value undef for all practical purposes is it that same as deleted item in FAT and should be treated by interpreter developers in the same way as "not found" item. "

        Might I ask where you got your information that Perl variables are relative to a file system designed in the 80's?

        In other words, before you make statements that relate the two together, you should at least test on another 3-4 programming languages and see how things are dealt with there first.

        At least that's what I'd do before making blanket complaints.

        Have you filed a bug report for this 'issue' with the p5p team?

        DB<64> p exists $main::{X} DB<65> $X = undef DB<66> p exists $main::{X} 1 DB<67>

        > Do not shoot the piano player, ... :-)

        Why would I?

        I'm not aware that Charles Aznavour spread fake news about programming ...

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

Re: Two meanings of undef
by BillKSmith (Monsignor) on Aug 16, 2020 at 16:07 UTC
    I wish to discuss your second example first. undef is a special 'value'. It is the default value given to a scalar when it is created. It can be assigned later, as you have shown. Its behavior depends on context.

    As a number, it is treated as zero. AS a string, it is treated as a null string. As a Boolean, it is treated as 'false'. As a argument to defined, it is the only value for which defined will return 'false'.

    ?perl -e"$line = undef; print 3 + $line" 3 ?perl -e"$line = undef; print '3' . $line" 3 ?perl -e"$line = undef; print 3 unless $line" 3 ?perl -e"$line = undef; print 3 unless defined $line" 3

    Your first example does not do what you think. try it. You probably mean:

    $current_time='14:30:05' (undef, $min, $sec)=split /\:/, $current_time

    I think of this as an idiomatic use which means exactly what you describe. That field of the assignment is ignored.

    Bill
      > I think of this as an idiomatic use which means exactly what you describe

      It's a documented behavior of list assignments.

      See perldata#List-value-constructors

      Lists may be assigned to only when each element of the list is itself legal to assign to:

      ...

      An exception to this is that you may assign to undef in a list. This is useful for throwing away some of the return values of a function:

      ($dev, $ino, undef, undef, $uid, $gid) = stat($file);

      update

      For the rest: Perl has the symbol undef acting like a constant for the "undefined value" and a builtin function undef(EXPR) to "undefine one variable" which also returns undef to the LHS.

      It might be confusing that they are equally named, but I rarely use the function anyway.

      PS:

      since constants are just special functions in Perl, it could be that undef and undef(EXPR) are implemented in one (magic) operator which does constant folding when called without arguments. But that's an implementation detail, located somewhere between parser and op-tree.

      undef

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

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2024-03-28 17:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found