Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

What protects me from doing this stupid thing..?

by Cody Pendant (Prior)
on Aug 11, 2007 at 23:59 UTC ( [id://631989]=perlquestion: print w/replies, xml ) Need Help??

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

I'd got into the habit of doing this:
$some_var = $some_possibly_undefined_var || 10
so that I get a default if the var isn't defined.

But then, genius that I am, I used a more complex version of it like this in an HTML::Template param() assignment.

$template->param( some_var => $hash{some_possibly_undefined_key} || 10 )
which doesn't work.

What I've told perl to do is to assign the non-existent variable, or do "10", is that right?

But I don't get a "contant in void context" warning the way I would if I just put:

10;
in the middle of my script.

Is there any way I could have caught that?



Nobody says perl looks like line-noise any more
kids today don't know what line-noise IS ...

Replies are listed 'Best First'.
Re: What protects me from doing this stupid thing..?
by kyle (Abbot) on Aug 12, 2007 at 00:13 UTC

    You can always parenthesize defensively.

    $template->param( some_var => ( $hash{some_possibly_undefined_key} || 10 ) )

    ...but it looks to me as if your example actually works as you intend.

    The big problem I see is that you default to 10 even if you have a defined value of 0 (see also True or False? A Quick Reference Guide).

Re: What protects me from doing this stupid thing..?
by FunkyMonk (Chancellor) on Aug 12, 2007 at 00:16 UTC
    so that I get a default if the var isn't defined
    No. What you get is a default if the var is false. undef, zero and "" are all values of false. What you want is the // operator, coming soon in perl 5.10. Until then, if you want to check for an expression being undefined, stay safe and use defined.

    It's late. I'm tired. I'm going to bed

      ...or, in the case of a hash, exists(), which doesn't, as i understand it, autovivify with a value of undef the key which had hitherto not existed in the hash.

        You're partly correct. In the case of this example, where there is only a single level hash, exists will not autovivify the key. However, if this was a complex data structure containing a HoH, HoA, AoH, etc, then the intermediate references (but not the terminal reference) would be autovivified*. To avoid autovivifying the intermediate structures you have to use exists to check each one as you go, or use something like tye's Data::Diver. See the example below.

        use strict; use warnings; use Data::Diver qw( Dive ); use Data::Dumper; my %h; # The exists function will autovivify intermediate keys print "Testing with exists\n"; printf "key1 %s exist\n", exists $h{key1} ? 'does' : 'does not'; printf "key1-key2 %s exist\n", exists $h{key1}{key2} ? 'does' : 'does +not'; printf "key1 %s exist\n", exists $h{key1} ? 'does' : 'does not'; print Dumper( \%h ); # Data::Diver's Dive will not autovivify intermediate keys print "\nTesting with Data::Diver\n"; my @values = Dive ( \%h, 'key3', 'key4' ); printf "key3-key4 %s exist\n", @values ? 'does' : 'does not'; print Dumper( \%h );
        Output:
        Testing with exists key1 does not exist key1-key2 does not exist key1 does exist $VAR1 = { 'key1' => {} }; Testing with Data::Diver key3-key4 does not exist $VAR1 = { 'key1' => {} };

        *You may know this, but someone else reading your reply may not realize the difference in behavior for single level vs multi level structures.

Re: What protects me from doing this stupid thing..?
by wind (Priest) on Aug 12, 2007 at 00:18 UTC

    perldoc perlop Operator Precedence Associativity

    The || operator has a higher precedence than the comma, so your code should work as you intend. What do you mean by, it doesn't work?

    As I read it, that should assign the param "some_var" to the value of supplied by the hash or 10 if that is false.

    - Miller

      Sorry, I've just realised that my error was elsewhere, and the code does in fact work. Thanks for the help with undefined versus false though.


      Nobody says perl looks like line-noise any more
      kids today don't know what line-noise IS ...
        Still, I thought there was (arguably) a valid point made.

        Given that perl -we '10' produces the "Useless use of a constant in void context" warning, couldn't it be argued (by someone that wanted to be extremely picky) that perl -we '0 || 10' should produce the same (or similar) warning ?

        Cheers,
        Rob
Re: What protects me from doing this stupid thing..?
by gam3 (Curate) on Aug 12, 2007 at 11:58 UTC
    It's not that pretty, but
    $template->param( some_var => 10, (some_var => $hash{some_possibly_undefined_key}) x!! exists($hash{so +me_possibly_undefined_key}), );
    will do what you want. Or
    $template->param( some_var => exists $hash{some_possibly_undefined_key} ? $hash{some_p +ossibly_undefined_key} : 10; );
    However, you might also try using Params::Validate
    { package MyTemplate; use base Template; use Params::Validate qw (validate); sub param { my $self = shift; my %p = validate(@_, { some_var => { default => 12, } }); $self->SUPER::param(%p); } }
    To actually answer your question, some things are hard to protect against and it is best to just try to avoid some constructs. For example you can write
    if ($a == 0) 
    
    or you can write
    if (0 == $a)
    
    using the second will keep you from the problem of writing if ($a = 0).
    -- gam3
    A picture is worth a thousand words, but takes 200K.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2024-04-25 08:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found