Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Sequential defined-or operators

by naikonta (Curate)
on Jan 14, 2008 at 06:01 UTC ( #662262=perlquestion: print w/ replies, xml ) Need Help??
naikonta has asked for the wisdom of the Perl Monks concerning the following question:

Everybody seems to be happy with the presence of defined-or (//) operator in Perl 5.10, including me. As I often write:
my $default = 0; my $input_number = $ARGV[0]; my $number = defined $input_number ? $input_number : $default;
Now I can write:
my $number = $input_number // $default;
Lacking of chances to download and install Perl 5.10 and test it myself (which can be read as 'lazy' :-) ), I wonder if any monks have experiences on using this one of new-long-waited-features in sequential. Take a look at this example:
my $default_theme = get_default_theme(); my $global_config = read_config('/path/to/config_file'); my $theme_config = read_config($global_config->{theme_file}); my $current_mode = get_current_mode(); my $theme = defined $global_config->{modes}{$current_mode}{theme} ? $global_config->{modes}{$current_mode}{theme} : defined $theme_config->{current_theme} ? $theme_config->{current_theme} : defined $default_theme ? $default_theme : 'none';
With defined-or operator, can I simply write
my $theme = $global_config->{modes}{$current_mode}{theme} // $theme_config->{current_theme} // $default_theme // 'none';
or, should I use some parens to delimit the (inner) expressions such as,
my $theme = ( ( $global_config->{modes}{$current_mode}{theme} // $theme_config->{current_theme} ) // $default_theme ) // 'none';
Is there any other alternative? Is this possible at all?

Thanks all for sharing your experiences.


Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Comment on Sequential defined-or operators
Select or Download Code
Re: Sequential defined-or operators
by ikegami (Pope) on Jan 14, 2008 at 06:04 UTC
    The second last snippet is much more readable than the last. An alternative is
    my $theme = $global_config->{modes}{$current_mode}{theme} // $theme_config->{current_theme} // $default_theme // 'none';
      It's wonderful, ikegami! My worries disappear right away.

      Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

        Just be careful with precedence. Absent prototypes overriding the default,

        my $value = $hash{$arg} // func $arg // 'default';
        means
        my $value = $hash{$arg} // func($arg // 'default');

        Putting parens around the low precedence bit solves the problem.

        my $value = $hash{$arg} // (func $arg) // 'default';

        Of course, with functions, you can also do

        my $value = $hash{$arg} // func($arg) // 'default';
      WWCD? (What would Conway Do?)

      ...Break long lines before an operator. That approach ensures that each line of the continued expression will start with an operator, which is unusual in Perl code. That way, as the reader's eye scans down the left margin of the code, its immediately obvious that an indented line is merely the continuation of the previous line, because it starts with an operator.

      The indenting of the second and subsequent lines of the expression is also critical...they should be indented to the starting column of the expression to which they belong.

      Hence, ikegami. (Although Conway likes to put the terminal semi-colon on a line by itself, to signal completion of the multi-line formula.)
        That approach ensures that each line of the continued expression will start with an operator
        Another reason I support this style is the starting operators can be made inline with the assignment operator where the line begins. I don't think it's so much unusual in Perl code, at least, it's not strange for me.

        However, I still much prefer (and get used) to break long lines after the operator because the adoption of \ (backslash) usage to break long lines in Unix/Linux convention. Still, both styles sign line continuation as we don't see the statement terminator (;) until the last line of the group.


        Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Re: Sequential defined-or operators
by Tux (Monsignor) on Jan 14, 2008 at 08:20 UTC

    It's chainable, just like ||. And it is available as a patch to 5.8.x since 5.8.0. See my CPAN home dir at the dor-* files


    Enjoy, Have FUN! H.Merijn
      Great to know that, cbu. Unfortunately, I have put myself away from doing manual installation for most software packages for the last few years, which may explain my laziness to install 5.10 in the first place :-) I think old habits should return again.

      Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Re: Sequential defined-or operators
by Util (Priest) on Jan 14, 2008 at 22:21 UTC

    While you remain pre-5.10, you might like this technique:

    use List::Util qw( first ); my $theme = first { defined $_ } ( $global_config->{modes}{$current_mode}{theme}, $theme_config->{current_theme}, $default_theme, 'none', );

      Thats all fine and good until your default value is ask_user(). Then this fails due to eager evaluation. // fixes this fortunately.
        It took me a second to understand that you are referring to the short-circuiting nature of //. If you needed the short-circuiting behaviour pre-5.10, here's one solution:
        sub first(&@) { my $cb = shift(@_); for (@_) { my $i = ref eq 'CODE' ? $_->() : $$_; my $rv; $rv = $cb->() for $i; return $i if $rv; } return; } my $theme = first { defined } \$global_config->{modes}{$current_mode}{theme}, \$theme_config->{current_theme}, \&ask_user, \'none';

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://662262]
Approved by ikegami
Front-paged by McDarren
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (11)
As of 2014-09-17 13:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (80 votes), past polls