lc() with undefined arg

Discussion in 'Perl Misc' started by Len@Weisberg.com, Aug 11, 2005.

  1. Guest

    I expected this to give a warning for "uninitialized value" :
    perl -w -e 'my $abc; print "\L$abc";'
    But it doesn't!

    Why is this different from:
    perl -w -e 'my $abc; print "$abc";'
    which DOES give the expected warning ?

    Is it documented that lc() doesn't mind an undefined argument ?
    Or is something else going on?

    I'm interested in this because the following would be kind of neat
    if I could trust that it would work cleanly into the future,
    even if Flag was missing from the hash:
    if ("\L$hash->{'Flag'}" eq 'yes') {...}

    If I don't understand why it works, I'll continue to use the rather
    messier:
    if (lc ($hash->{'Flag'} || '') eq 'yes') {...}

    (BTW, about omitting the quotes, as in $hash->{Flag} :
    is this considered sound practice, or is it just lazy ?)

    Cheers,

    -Len
    , Aug 11, 2005
    #1
    1. Advertising

  2. Paul Lalli Guest

    wrote:
    > I expected this to give a warning for "uninitialized value" :
    > perl -w -e 'my $abc; print "\L$abc";'
    > But it doesn't!
    >
    > Why is this different from:
    > perl -w -e 'my $abc; print "$abc";'
    > which DOES give the expected warning ?
    >
    > Is it documented that lc() doesn't mind an undefined argument ?


    Not that I can see anywhere, but that certainly does seem to be the
    case:

    perl -MData::Dumper -wle '$bar = lc($foo); print Dumper(\$foo, \$bar);'
    $VAR1 = \undef;
    $VAR2 = \'';

    > if (lc ($hash->{'Flag'} || '') eq 'yes') {...}
    >
    > (BTW, about omitting the quotes, as in $hash->{Flag} :
    > is this considered sound practice, or is it just lazy ?)


    It could come back to bite you one day if: 1) a future release of Perl
    suddenly introduces a Flag() function; 2) your code is modified to
    include a Flag() subroutine; 3) your code is modified to import a
    module which exports a Flag() subroutine; 4) your code is modified to
    include a constant named Flag. If you're worried about one or more of
    those, much safer to use the quotes.

    Paul Lalli

    Paul Lalli
    Paul Lalli, Aug 11, 2005
    #2
    1. Advertising

  3. Guest

    >> Is it documented that lc() doesn't mind an undefined argument ?
    >
    >Not that I can see anywhere, but that certainly does seem to be the
    >case:


    Thanks, Paul, for the quick reply. If no one can assure me that
    this is documented behavior, I won't depend on it.

    Should this failure to warn be reported as a bug?
    If so, what is the best way to do that?

    Cheers,
    -Len
    , Aug 11, 2005
    #3
  4. Paul Lalli Guest

    wrote:
    > >> Is it documented that lc() doesn't mind an undefined argument ?

    > >
    > >Not that I can see anywhere, but that certainly does seem to be the
    > >case:

    >
    > Thanks, Paul, for the quick reply. If no one can assure me that
    > this is documented behavior, I won't depend on it.
    >
    > Should this failure to warn be reported as a bug?
    > If so, what is the best way to do that?


    I'm not convinced that it is a bug. Unexpected and undocumented,
    certainly. But I think a "bug" is something that directly contradicts
    the documentation. I think this just qualifies as "undefined
    behavior." Regardless, the proper way to submit Perl bug reports is
    via perlbug. Read about its use at:
    perldoc perlbug

    Paul Lalli
    Paul Lalli, Aug 11, 2005
    #4
  5. Paul Lalli Guest

    Stephen Hildrey wrote:
    > Paul Lalli wrote:
    > > wrote:
    > >>(BTW, about omitting the quotes, as in $hash->{Flag} :
    > >> is this considered sound practice, or is it just lazy ?)

    > >
    > >
    > > It could come back to bite you one day if: 1) a future release of Perl
    > > suddenly introduces a Flag() function; 2) your code is modified to
    > > include a Flag() subroutine; 3) your code is modified to import a
    > > module which exports a Flag() subroutine; 4) your code is modified to
    > > include a constant named Flag. If you're worried about one or more of
    > > those, much safer to use the quotes.

    >
    > Not true.
    >
    > A simple expression (like a single token) inside the {} will
    > automatically be treated as quoted, so the following:
    >
    > perl -w -MData::Dumper -e 'sub foo { return "bar"; } my %h; $h{foo} =
    > "baz"; print Dumper(\%h)'
    >
    > will give the expected:
    >
    > $VAR1 = {
    > 'foo' => 'baz'
    > };


    Hrm. I was just completely wrong. I was misremembering the docs.
    Thanks very much for the correction. An my apologies to the OP for the
    misinformation.

    Paul Lalli
    Paul Lalli, Aug 11, 2005
    #5
  6. wrote:
    > Is it documented that lc() doesn't mind an undefined argument ?


    I can't see it documented, but it is a common idiom when using CGI.pm to
    use:

    my $foo = lc(param('foo'));

    for exactly the purpose you describe - supressing the undef warnings.

    I am not a Perl internals hacker, but at a guess (and I am probably
    wrong) this source looks relevant:

    if (!len) {
    SvUTF8_off(TARG); /* decontaminate */
    sv_setpvn(TARG, "", 0);
    SETs(TARG);
    }

    (perl 5.8.6 - pp.c lines 3587 - 3591)

    HTH,
    Steve
    Stephen Hildrey, Aug 11, 2005
    #6
  7. Paul Lalli wrote:
    > wrote:
    >>(BTW, about omitting the quotes, as in $hash->{Flag} :
    >> is this considered sound practice, or is it just lazy ?)

    >
    >
    > It could come back to bite you one day if: 1) a future release of Perl
    > suddenly introduces a Flag() function; 2) your code is modified to
    > include a Flag() subroutine; 3) your code is modified to import a
    > module which exports a Flag() subroutine; 4) your code is modified to
    > include a constant named Flag. If you're worried about one or more of
    > those, much safer to use the quotes.


    Not true.

    A simple expression (like a single token) inside the {} will
    automatically be treated as quoted, so the following:

    perl -w -MData::Dumper -e 'sub foo { return "bar"; } my %h; $h{foo} =
    "baz"; print Dumper(\%h)'

    will give the expected:

    $VAR1 = {
    'foo' => 'baz'
    };

    Similarly,

    perl -w -MData::Dumper -e 'my %h; $h{print} = "baz"; print Dumper(\%h)'

    will give the expected:

    $VAR1 = {
    'print' => 'baz'
    };

    Obviously clarity is the priority and if it is unclear what is going on
    then either quote it or include a comment.

    As to the use of constants, perldoc constant says it more succinctly
    than I can:

    "You can get into trouble if you use constants in a context which
    auto-matically quotes barewords (as is true for any subroutine call).
    For example, you can't say $hash{CONSTANT} because "CONSTANT" will be
    interpreted as a string. Use $hash{CONSTANT()} or $hash{+CONSTANT} to
    prevent the bareword quoting mechanism from kicking in."

    Steve
    Stephen Hildrey, Aug 11, 2005
    #7
  8. Guest

    Re:barewords as hashkey [was: lc() with undefined arg]

    Paul Lalli wrote:
    > Stephen Hildrey wrote:
    > > Paul Lalli wrote:
    > > > wrote:
    > > >>(BTW, about omitting the quotes, as in $hash->{Flag} :
    > > >> is this considered sound practice, or is it just lazy ?)
    > > >


    Thanks for the thoughtful discussion. Just to clarify:
    So the upshot is that the use of barewords as hash keys is a sound
    and
    recommended practice?

    Cheers,
    -Len
    , Aug 12, 2005
    #8
  9. Re: barewords as hashkey [was: lc() with undefined arg]

    wrote:

    > Thanks for the thoughtful discussion. Just to clarify:
    > So the upshot is that the use of barewords as hash keys is a sound
    > and
    > recommended practice?


    It boils down to this: if your hash key is a bareword, you can leave out
    the quotes; anything more complex as the key and Perl will interpret it
    as an expression.

    It's certainly a valid practice, whether it's sound and/or recommended
    it probably a matter of taste. I'd argue "be consistent / be nice" here,
    with a dose of "be understandable" :)

    Steve
    Stephen Hildrey, Aug 12, 2005
    #9
  10. Also sprach Stephen Hildrey:

    > wrote:
    >> Is it documented that lc() doesn't mind an undefined argument ?

    >
    > I can't see it documented, but it is a common idiom when using CGI.pm to
    > use:
    >
    > my $foo = lc(param('foo'));
    >
    > for exactly the purpose you describe - supressing the undef warnings.
    >
    > I am not a Perl internals hacker, but at a guess (and I am probably
    > wrong) this source looks relevant:
    >
    > if (!len) {
    > SvUTF8_off(TARG); /* decontaminate */
    > sv_setpvn(TARG, "", 0);
    > SETs(TARG);
    > }
    >
    > (perl 5.8.6 - pp.c lines 3587 - 3591)


    It's not really surprising that this behaviour is implemented somewhere
    in the source. However, the code you quote is common in string handling
    routines that usually upgrade undef to the empty string. The actual
    check for emitting the warning normally happens before. But not in the
    case of (uc|lc)(_first)? and possibly others for no apparent reason.

    I'm inclined to say this is a bug unless someone is able to explain the
    reasoning behind that behaviour.

    Tassilo
    --
    use bigint;
    $n=71423350343770280161397026330337371139054411854220053437565440;
    $m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
    Tassilo v. Parseval, Aug 12, 2005
    #10
  11. Guest

    Tassilo v. Parseval wrote:
    > Also sprach Stephen Hildrey:
    >
    > > wrote:
    > >> Is it documented that lc() doesn't mind an undefined argument ?

    > >
    > > I can't see it documented, but it is a common idiom when using CGI.pm to
    > > use:
    > >
    > > my $foo = lc(param('foo'));
    > >
    > > for exactly the purpose you describe - supressing the undef warnings.
    > >
    > > I am not a Perl internals hacker, but at a guess (and I am probably
    > > wrong) this source looks relevant:
    > >
    > > if (!len) {
    > > SvUTF8_off(TARG); /* decontaminate */
    > > sv_setpvn(TARG, "", 0);
    > > SETs(TARG);
    > > }
    > >
    > > (perl 5.8.6 - pp.c lines 3587 - 3591)

    >
    > It's not really surprising that this behaviour is implemented somewhere
    > in the source. However, the code you quote is common in string handling
    > routines that usually upgrade undef to the empty string. The actual
    > check for emitting the warning normally happens before. But not in the
    > case of (uc|lc)(_first)? and possibly others for no apparent reason.
    >
    > I'm inclined to say this is a bug unless someone is able to explain the
    > reasoning behind that behaviour.


    I was starting to believe it might be a bug but string operators
    (at least the ones below) behave like the string function 'uc'
    as well:

    # neither emit a warning
    perl -wle 'my $foo;print $foo .""'
    perl -wle 'my $foo;print $foo x 3'


    --
    Charles DeRykus
    , Aug 12, 2005
    #11
  12. Also sprach :

    > Tassilo v. Parseval wrote:


    [ lc(undef) wont warn ]

    >> I'm inclined to say this is a bug unless someone is able to explain the
    >> reasoning behind that behaviour.

    >
    > I was starting to believe it might be a bug but string operators
    > (at least the ones below) behave like the string function 'uc'
    > as well:
    >
    > # neither emit a warning
    > perl -wle 'my $foo;print $foo .""'
    > perl -wle 'my $foo;print $foo x 3'


    This is a family of special cases. It also applies to numerical values:

    my $a;
    $a++; # never warns

    The idea is to allow for something like this:

    my $var;
    while () {
    ...
    $var .= $char;
    }

    without the need for any initial value for $var.

    But I don't see how the functions mentioned in this thread fall into
    this category. Meanwhile, I found one other builtin that wont warn on
    undef: 'reverse' in scalar context.

    What is worse about these cases is the fact that after applying any of
    these functions, the value is no longer undef but the empty string. In a
    context of a program these two values might have a very different
    meaning and silently transforming one into the other is wrong.

    Tassilo
    --
    use bigint;
    $n=71423350343770280161397026330337371139054411854220053437565440;
    $m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
    Tassilo v. Parseval, Aug 12, 2005
    #12
  13. Anno Siegel Guest

    Tassilo v. Parseval <> wrote in comp.lang.perl.misc:
    > Also sprach :
    >
    > > Tassilo v. Parseval wrote:


    [...]

    > But I don't see how the functions mentioned in this thread fall into
    > this category. Meanwhile, I found one other builtin that wont warn on
    > undef: 'reverse' in scalar context.
    >
    > What is worse about these cases is the fact that after applying any of
    > these functions, the value is no longer undef but the empty string. In a
    > context of a program these two values might have a very different
    > meaning and silently transforming one into the other is wrong.


    That's only a consequence of some functions stringifying their argument,
    the same goes for hash keys. I wouldn't worry about it, a programmer
    doesn't expect a function like lc to return its argument unchanged. I think
    it's just a missing "uninitialized" warning -- add that and reverse and
    lc fit right in.

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
    Anno Siegel, Aug 12, 2005
    #13
  14. Also sprach Anno Siegel:

    > Tassilo v. Parseval <> wrote in comp.lang.perl.misc:
    >> Also sprach :
    >>
    >> > Tassilo v. Parseval wrote:

    >
    > [...]
    >
    >> But I don't see how the functions mentioned in this thread fall into
    >> this category. Meanwhile, I found one other builtin that wont warn on
    >> undef: 'reverse' in scalar context.
    >>
    >> What is worse about these cases is the fact that after applying any of
    >> these functions, the value is no longer undef but the empty string. In a
    >> context of a program these two values might have a very different
    >> meaning and silently transforming one into the other is wrong.

    >
    > That's only a consequence of some functions stringifying their argument,
    > the same goes for hash keys. I wouldn't worry about it, a programmer
    > doesn't expect a function like lc to return its argument unchanged. I think
    > it's just a missing "uninitialized" warning -- add that and reverse and
    > lc fit right in.


    Yes, I am not worried about the empty string that is produced but the
    fact that it happens silently. When I get warnings about uninitialized
    values it's almost always a bug in my programs. So that's a warning I
    cannot do without.

    Tassilo
    --
    use bigint;
    $n=71423350343770280161397026330337371139054411854220053437565440;
    $m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
    Tassilo v. Parseval, Aug 13, 2005
    #14
  15. Guest

    I have checked these results on various versions of Perl on
    a couple different machines going back to v5.004_04 .

    My results:

    For ALL versions tested, there are NO warnings for:
    perl -wle 'my $foo ;
    print "\L$foo", lc $foo, uc $foo, ucfirst $foo, $foo x 1'

    For ALL versions tested, there IS a warning for:
    perl -wle 'my $foo ; print reverse $foo' ;

    For ALL versions tested, EXCEPT v5.6.1 , there IS a warning for:
    perl -wle 'my $foo ; print $foo . ""' ;

    So I would be interested in what versions gave Charles and Tassilo
    the results they reported:
    Charles DeRykus:
    > # neither emit a warning
    > perl -wle 'my $foo;print $foo .""'


    Tassilo v. Parseval:
    > Meanwhile, I found one other builtin that wont warn on
    > undef: 'reverse' in scalar context.


    Cheers,
    -Len
    , Aug 13, 2005
    #15
  16. Also sprach :

    > I have checked these results on various versions of Perl on
    > a couple different machines going back to v5.004_04 .
    >
    > My results:
    >
    > For ALL versions tested, there are NO warnings for:
    > perl -wle 'my $foo ;
    > print "\L$foo", lc $foo, uc $foo, ucfirst $foo, $foo x 1'
    >
    > For ALL versions tested, there IS a warning for:
    > perl -wle 'my $foo ; print reverse $foo' ;


    I said reverse in scalar context. The above is list context. The warning
    you get is for the uninitialized value that print receives. Try:

    perl -wle 'print scalar reverse undef'

    > For ALL versions tested, EXCEPT v5.6.1 , there IS a warning for:
    > perl -wle 'my $foo ; print $foo . ""' ;


    You don't get a warning for

    $foo .= "";

    This is the special case I mentioned.

    Tassilo
    --
    use bigint;
    $n=71423350343770280161397026330337371139054411854220053437565440;
    $m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
    Tassilo v. Parseval, Aug 13, 2005
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mantorok Redgormor
    Replies:
    70
    Views:
    1,750
    Dan Pop
    Feb 17, 2004
  2. n00m
    Replies:
    5
    Views:
    396
  3. Replies:
    7
    Views:
    174
  4. VK
    Replies:
    45
    Views:
    590
    Dr John Stockton
    Sep 12, 2006
  5. Replies:
    21
    Views:
    293
    Barry Schwarz
    Mar 5, 2014
Loading...

Share This Page