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

Strange syntax question

by gri6507 (Deacon)
on Aug 14, 2013 at 16:09 UTC ( #1049437=perlquestion: print w/replies, xml ) Need Help??
gri6507 has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,

I am taking over maintenance of some Perl code which was written by a, shall we say, Perl non-expert. However, this person did have a strong C background. I believe that caused him to write a line of Perl code which currently has me baffled. Here's the relevant section:

use warnings; use strict; my $foo = "bar"; DoIt(); sub DoIt { my $it = shift // $foo; # Given the C background of the author, I can see why the line was + written as is. However, it was supposed to be # my $it = shift; // $foo print "it is '$it'\n"; }

Oddly, the output is it is 'bar', although I do not understand why. Can someone please enlighten me what the line in question actually does?

Replies are listed 'Best First'.
Re: Strange syntax question
by chromatic (Archbishop) on Aug 14, 2013 at 16:15 UTC

    // isn't a comment in Perl. It's the defined-or operator. It's an infix operator, so it comes between two operands. If the left operand evaluates to a defined value, the operator produces the left operand's value. If the left operand evaluates to an undefined value, the operator produces the right operand's value.

    In other words, shift off the first parameter to the function and assign its value to $it. If that's not a defined value, assign the value of $foo to $it instead.

    Improve your skills with Modern Perl: the free book.

Re: Strange syntax question
by Utilitarian (Vicar) on Aug 14, 2013 at 16:15 UTC
    from perldoc perlop:
    C-style Logical Defined-Or Although it has no direct equivalent in C, Perl's "//" operator + is related to its C-style or. In fact, it's exactly the same as " +||", except that it tests the left hand side's definedness instead o +f its truth. Thus, "$a // $b" is similar to "defined($a) || $b" (exc +ept that it returns the value of $a rather than the value of "defined($a +)") and yields the same result as "defined($a) ? $a : $b" (except that +the ternary-operator form can be used as a lvalue, while "$a // $b" cannot). This is very useful for providing default values for variables. If you actually want to test if at least one of $a +and $b is defined, use "defined($a // $b)". The "||", "//" and "&&" operators return the last value evaluat +ed (unlike C's "||" and "&&", which return 0 or 1). Thus, a reason +ably portable way to find out the home directory might be: $home = $ENV{HOME} // $ENV{LOGDIR} // (getpwuid($<))[7] // die "You're homeless!\n"; In particular, this means that you shouldn't use this for selec +ting between two aggregates for assignment: @a = @b || @c; # this is wrong @a = scalar(@b) || @c; # really meant this @a = @b ? @b : @c; # this works fine, though As more readable alternatives to "&&" and "||" when used for co +ntrol flow, Perl provides the "and" and "or" operators (see below). +The short-circuit behavior is identical. The precedence of "and" a +nd "or" is much lower, however, so that you can safely use them after a + list operator without the need for parentheses: unlink "alpha", "beta", "gamma" or gripe(), next LINE; With the C-style operators that would have been written like th +is: unlink("alpha", "beta", "gamma") || (gripe(), next LINE); Using "or" for assignment is unlikely to do what you want; see +below.

    print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
Re: Strange syntax question
by choroba (Bishop) on Aug 14, 2013 at 16:16 UTC
    // is the Perl "defined or" operator. Comments are delimited by # only. What the line does can be extended to:
    my $it; $it = shift; defined $it or $it = $foo;
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Strange syntax question
by betterworld (Curate) on Aug 14, 2013 at 17:16 UTC

    Are you sure this is a typo? It seems to me that the author knew exactly what the code was supposed to do. Using "//" like this is a common idiom to have "default arguments".

    If the "$foo" was meant to be a comment, then what should be in "$it"? An undefined "$it" would produce a warning.

Re: Strange syntax question (perlop // dor)
by Anonymous Monk on Aug 14, 2013 at 16:14 UTC
Re: Strange syntax question
by Laurent_R (Canon) on Aug 14, 2013 at 18:45 UTC

    some Perl code which was written by a, shall we say, Perl non-expert.

    Possibly not an expert, but probably not a total newbie either. ;-)

Re: Strange syntax question
by marinersk (Priest) on Aug 14, 2013 at 17:34 UTC
    So, to translate the operational effect, the original author of that line of code seems to be using that one-liner to establish a default value for the parameter to Doit() in the event it is called without a parameter. Furthermore, maintenance of that default value is moved to the top of the source file for easy modification.

    Nice trick. I think I'll be taking that one home today.

      Take it home and use it, certainly, but don't leave that loaded global variable lying around where it can hurt someone!

      >perl -wMstrict -le "use constant FOO => 'bar'; ;; DoIt(); ;; sub DoIt { my $it = shift // FOO; print qq{it is '$it'}; } " it is 'bar'

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1049437]
Approved by Athanasius
[Corion]: Hmm. I think overnight I decided on simplifying some code. I have plugin classes that do data import (.csv, .yml, .json) and for that create objects on which then ->load() is called. But YAML::XS doesn't have an object, so I wrote my own wrapper.
[Corion]: This evening, I'll kill that wrapper again, and just call LoadFile() in the plugin class directly instead of creating a go-between object for no real gain.

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (8)
As of 2018-05-22 10:59 GMT
Find Nodes?
    Voting Booth?