views:

100

answers:

3

I am completely new to Perl. I needed to use an external module HTTP::BrowserDetect. I was testing some code and tried to get the name of the OS from os_string method. So, I simply initialized the object and created a variable to store the value returned.

my $ua = HTTP::BrowserDetect->new($user_agent);
my $os_name = $ua->os_string();

print "$user_agent $os_name\n";

there are some user agents that are not browser user agents so they won't get any value from os_string. I am getting an error Use of uninitialized value $os_name in concatenation (.) or string

How do I handle such cases when the $os_name is not initialized because the method os_string returns undef (this is what I think happens from reading the module source code). I guess there should be a way to give a default string, e.g. No OS in these cases.

+4  A: 
my $os_name = $ua->os_string() || 'No OS';

If $ua->os_string() is falsy (ie: undef, zero, or the empty string), then the second part of the || expression will be evaluated (and will be the value of the expression).

cHao
thanks, this truly was a very simple problem indeed :).
sfactor
+7  A: 

Please note: the original answer's approach ( $var = EXPRESSION || $default_value ) would produce the default value for ANY "Perl false values" returned from the expression, e.g. if the expression is an empty string, you will use the default value instead.

In your particular example it's probably the right thing to do (OS name should not be an empty string), but in general case, it can be a bug, if what you actually wanted was to only use the default value instead of undef.

If you only want to avoid undef values, but not empty string or zeros, you can do:

  • Perl 5.10 and later: use the "defined-or operator" (//):

    my $os_name = $ua->os_string() // 'No OS';
    
  • Perl 5.8 and earlier: use a conditional operator because defined-or was not yet available:

    my $os_string = $ua->os_string(); # Cache the value to optimize a bit
    my $os_name = (defined $os_string) ? $os_string : 'No OS';
    # ... or, un-optimized version (sometimes more readable but rarely)
    my $os_name = (defined $ua->os_string()) ? $ua->os_string() : 'No OS';
    

A lot more in-depth look at the topic (including details about //) are in brian d foy's post here: http://www.effectiveperlprogramming.com/blog/704

DVK
A: 

Are you looking for defined?

dvhh