Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

defined vs null string

by Anonymous Monk
on Aug 30, 2011 at 13:20 UTC ( #923210=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have confusion about a very simple issue. I am unable to completely understand this simple concepts of 'defined', undef, null strings in perl.

I tried to read a bit and was not sure. I wrote a snippet to explain to you my confusion.

my $y; if (defined $y) { print "Y is defined\n"; } else { print "Y is not defined\n"; } if ($y eq "") { print "Y is null string\n"; } else { print "Y is not null string\n"; }

The above gives me

Y is not defined Y is null string
Y is not defined and but it equates to a null string. How does the Perl concepts compare to a language like C. Thank you.

Replies are listed 'Best First'.
Re: defined vs null string
by blue_cowdawg (Monsignor) on Aug 30, 2011 at 13:37 UTC
        Y is not defined and but it equates to a null string. How does the Perl concepts compare to a language like C. Thank you.

    Here is a classic case of why you should use strict; and use warnings; when you are writing Perl.

    The first thing that jumps out at me is that Perl is not like C, a compiled language. Perl is an interpreted language and the use of my $y; is to establish the context of the variable not "define it" in the classical sense of the term. As long as you do not assign a value to $y it will have the psuedo-value of undef and hence the evaluation of the function defined($y) is going to return truefalse.

    Just for tee-hees and ha-has I took your code and started playing around with it. First thing I did was add use strict; followed by use warnings;. All was happy util the  if ($y eq "") conditional whereupon the warning Use of uninitialized value in string eq at line 14 was issued.

    OK... so let's initialize the variable.

    my $y = "";
    Now the output becomes:
    Y is defined Y is null string

    Hope this helps.

    updated:DOH! Saying true when I meant false....

    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: defined vs null string
by zentara (Archbishop) on Aug 30, 2011 at 14:13 UTC
    Reading perldoc -f defined will be illuminating.

    defined EXPR defined Returns a Boolean value telling whether EXPR has a value other than the undefined value "undef". If EXPR is not present, $_ is checked.

    An interesting thing to notice, is that defined returns nothing if something is undef. But it prints a 1 if defined. Sort of an asymetric boolean. One might expect 0 to be printed, but that return value would be defined, and would screw up the defined function used in more complex logic.

    #!/usr/bin/perl use warnings; use strict; print defined (undef) ,"\n"; # prints nothing but a newline my $y = undef; print defined ($y),"\n"; # prints nothing but a newline my $x = ''; print defined ($x), "\n"; # prints a 1

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      An interesting thing to notice, is that defined returns nothing if something is undef. But it prints a 1 if defined.

      Perl functions/operators do not return "nothing".    defined returns either "TRUE" or "FALSE", which is 1 for true or "" for false.

Re: defined vs null string
by AR (Friar) on Aug 30, 2011 at 13:30 UTC

    I highly recommend you use warnings and use strict in all of your code, no matter how short and contrived it is. Re-run your above code with warnings and strict and see what happens.

Re: defined vs null string
by cdarke (Prior) on Aug 30, 2011 at 14:50 UTC
    Y is not defined and but it equates to a null string. How does the Perl concepts compare to a language like C

    The closest thing in C to an undefined value is when a variable is not initialised. For example:
    int x; printf("%d",x);
    will give you whatever junk is in memory, it is unlikely that the value will be zero. In Perl we don't have that problem, every scalar has the value undef until you assign it otherwise. This can be flagged as an error or warning should you want it (that's one reason for use warnings and use strict).

    Worse, an unitialised string in C can cause your program to crash:
    char name[42]; printf("%s",name);
    could cause printf to run into an address which is illegal and crash the program. It might not - it might hit a zero delimiter by coincidence, but then you get junk displayed. No such problems in Perl.

    A "null string" is, I assume, an empty string, 0x00 in C. One difference with C is that even a null string will require an array of at least one byte. char *pName = NULL; is not an empty string in C, it is a pointer with a value of zero. That might be semantics, but in C (not in C++) NULL is a pointer value.

    Take a look at a Perl scalar string variable using Devel::Peek::Dump. Dump the variable as you change its size, and look at the amount of memory used (LEN). Now undef the value and see the difference:
    use strict; use warnings; use Devel::Peek; my $str = ""; Dump($str); $str = "Fred Bloggs"; Dump($str); $str = "This is a much, much longer string"; Dump($str); $str = ""; Dump($str); undef $str; Dump($str);
    See the difference between setting a string to be empty and using undef. Would it have made a difference if you assigned undef to the string instead of using undef as a function?
Re: defined vs null string
by BrowserUk (Pope) on Aug 30, 2011 at 17:42 UTC

    I think that the source of your confusion may be that if (defined $y) { is not testing whether the variable $y is defined.

    It is testing whether the variable $y is currently set to a defined value.

    In C, the is the concept of "defining variables" (which somewhat conflates with the concept of "declaring variables"), and may be the source of the confusion here, in that the declaration my $y; is also sometimes referred to as "defining $y".

    But that has litte or nothing to do with the use of the built-in defined function, which tests whether the value held by the variable is a defined value, not whether the variable itself has been declared (or defined :).

    In retrospect, defined might have been better named notUndef()

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: defined vs null string
by ikegami (Pope) on Aug 30, 2011 at 17:22 UTC

    eq is the string comparison operator. It compares strings. It therefore needs strings. If you pass it something that isn't a string, it's coerced into a string. In the case of undef, that means an empty string, but you get a warning for doing this.

    You want «defined($y) && !length($y)» or «defined($y) && $y eq ''».

Re: defined vs null string
by roboticus (Chancellor) on Aug 30, 2011 at 18:35 UTC

    You asked about how it compares with C, so here's a C version:

    #include <stdio.h> #include <string.h> char *undef; char *def_empty = ""; char *def = "foo bar"; void check(char *t) { if (t) { if (strlen(t)) { printf("Defined loc=%p, val='%s'\n", t, t); } else { printf("Empty string: loc=%p\n", t); } } else { printf("Undefined (null ptr)\n"); } } int main(int, char **) { check(undef); check(def_empty); check(def); return 0; }

    It gives us:

    $ ./a.exe Undefined (null ptr) Empty string: loc=0x4020e5 Defined loc=0x4020e6, val='foo bar'


    When your only tool is a hammer, all problems look like your thumb.

      That would be closer to

      sub SvPVX { unpack 'J', pack 'p', $_[0] } if (defined $y) { if (length($y)) { printf("Defined loc=%X, val='%s'\n", SvPVX($y), $y); } else { printf("Empty string: loc=%X\n", SvPVX($y)); } } else { printf("Undefined (null ptr)\n"); }

      So you completely removed the case the OP was asking about.

      The C equivalent would be closer to the following (memory leak aside):

      Scalar* stringify(Scalar* sv) { if (scalar_type(sv) == undefined) { fprintf(STDERR, "Use of unitialised value\n"); return NewEmptyStringScalar(); } else if (scalar_type(sv) == string) { return sv; } else if (scalar_type(sv) == ...) { ... } else ... } int eq(Scalar* sv1, Scalar* sv2) { return strcmp( stringify(sv1)->string_buffer, stringify(sv2)->string_buffer ) == 0; }
Re: defined vs null string
by Anonymous Monk on Aug 30, 2011 at 19:09 UTC
    I appreciate all your your valuable time. I must say it would take me a bit of a time to absorb everything you have said.

    I had not used the 'warning' or 'strict' just to see what happens to uninitialized variables

    I misunderstood (as has been rightly pointed out) 'defined' to mean existence of a variable.

    I had given the example so that I could get a real understanding of how defined and undef are used in Perl more in a general way. I must say, I am wiser.

    However, there is this one specific situation where I make use of 'defined'.

    I write small CGI/Perl programs from time to time. I would do something like the following, without having given much thought to it.

    my $query = CGI->new; my $p = $query->param('VAR'); if (defined $p && $p ne "") { # To see if $p had non-null value # Do something }

    Now the call to param would return 'undef' if VAR was not passed in to the CGI script. However, VAR could have been passed an empty string. In this case though, I am assuming the $p would be initialized to "". So $p could be undef or ""

    Without my understanding of how variables are initialized in Perl (with my exposure to C), I always wondered whether the 'If' statement above made sense. In other words, did I need to test for both 'defined' and null string.

      if (defined $p && $p ne "") { # To see if $p had non-null value # Do something }
      This makes sense. It is technically redundant: 'undef' evaluates to the empty string in string context, so undef ne "" is false. However, evaluating undef in a string context gives you a warning if use warnings is turned on, so what you wrote is the proper thing to do.
Re: defined vs null string
by sundialsvc4 (Abbot) on Aug 31, 2011 at 16:17 UTC

    In the case of memory variables, a variable either “has a value” or “it has no value at all.”   This is the meaning of undef.   In fact, it is useful to think that “a variable which has no value ... has a value, and that value is:   undef.”

    SQL databases define a similar concept, NULL, for the same reason.   Database interface layers like DBI ordinarily recognize undef as an indicator that a column should be set to (or that it presently is...) NULL, but in other language implementations this might not strictly be the case.   Microsoft’s Variant data-type system, for example, defines VarEmpty and VarNull as two separate possibilities in the underlying storage-record which defines a Variant value.

    In both cases, “the absence of any value at all” is purposely distinct from both “zero” and “empty string.”   Both of these are values.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://923210]
Approved by toolic
Front-paged by planetscape
[choroba]: Algorithm::Loops
[Corion]: choroba: I'm using that to generate the permutations, but I don't know how the user can pass the intended values to my function in a sane way
[Corion]: I have a prototype that permutes the get_parameters, but the values used for the get parameters should be different from the values used for the headers and potentially for parts of the URL
[Corion]: But yes, in general, my approach will be "split the URL into another set of parameters, generate an array of allowed values for each parameter and then NestedLoops() over the set"
[choroba]: hmm... so you need something like bag from Test::Deep, but not for checking, but for generation
[Corion]: This has the dual use of easily requesting sequential URLs and also being suitable for testing
[Corion]: For testing, I want to skip all tests with the same value(s) once one test fails to cut down on the number of failing tests
[Corion]: choroba: Yes, in a way I
[Corion]: ... I'm treating the incoming value sets as bags... Maybe I'll just put the burden on the user, at least in the first attempt at a full API. generate( headers => [{ 'Content-Type' => 'text/plain' }, {'Content-Type' => 'text/json' ] ), even ...
[Corion]: ... if that is cumbersome for the caller to specify. On the other hand, maybe there isn't that big a need for permuting the header values

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2017-01-17 08:20 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (152 votes). Check out past polls.