Perl Idiom // 0 [duplicate] - perl

I'm new to Perl and came across this piece of code at work, I search for a while but did not find the answer. Can anyone help to explain its function in plain english? thanks.
my $abc = delete $args{ 'abc' } // croak 'some information!';

From this page here: http://perldoc.perl.org/perlop.html#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 of its truth. Thus, EXPR1 // EXPR2 returns the value of EXPR1 if it's defined, otherwise, the value of EXPR2 is returned. (EXPR1 is evaluated in scalar context, EXPR2 in the context of // itself). Usually, this is the same result as defined(EXPR1) ? EXPR1 : EXPR2 (except that the ternary-operator form can be used as a lvalue, while EXPR1 // EXPR2 cannot, and EXPR1 will only be evaluated once). 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).

Check for Logical Defined-Or in perlop, it is similar to || but it checks for undef value (not false one).
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 of its truth.
So in short,
my $abc = delete $args{ 'abc' } // croak 'some information!';
will croak when $args{ 'abc' } returns undef value.

Related

What is the definition of stringwise equality in Perl?

I was curious about the results of the following perl snippets:
my $var1 ;
my $var2 ;
if( $var1 eq $var2 ) {
print "yes";
} else {
print "no";
}
and
my $var1 ;
my $var2 = "";
if( $var1 eq $var2 ) {
print "yes";
} else {
print "no";
}
They turn out to be yes(Perl 5.16).
Unlike javascript specificaton, there is clear description of Equality Comparison Algorithm(http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3), the perl doc for Equality Operators says:
Binary "eq" returns true if the left argument is stringwise equal to the right argument.
But what is the definition of stringwise equality?
You're not having a problem with the definition of stringwise equality. What you don't seem to have wrapped your head arround yet is the concept of stringification. In this particular case, undef stringifies to ''.
Perl has monomorphic operators (mostly) and contextually polymorphic data types.
What this means is that it is the operator that dictates how the data is represented. The eq operator is for stringwise equality. The == operator is for numeric equality. When == is applied to strings, they are treated as numbers. When eq is applied to numbers, they are treated as strings. Each of these internal transformations follow a very specific set of rules.
Thus, when you apply a stringwise operator to a pair of values, those values will be treated as strings. When you apply a numeric operator to a pair of values, they will be treated as numbers.
In your second example, $var1 contains undef, and $var2 contains an empty string. When you compare $var1 eq $var2, the rules of stringification are applied to the operands. $var2 is already a string. But $var1 must be stringified before it can be compared. The rule of stringification for an undefined value is to treat it as an empty string. So $var1 eq $var2 is seen by the eq operator as '' eq '', which is to say, empty string eq empty string.
TRUE.
Note: In modern versions of Perl, using an undefined scalar variable in a stringwise operation only results in stringification for the duration of the operation; the underlying data in the container isn't altered. (see perldata).
perldata is one resource on this topic.
Your definition question has been answered by DavidO, but the (probably) most important piece of information is in TLP's comment - you should always use these two at the top of every script:
use strict;
use warnings;
The one relevant in this case is use warnings, which will produce the following warning:
Use of uninitialized value $var1 in string eq
Some programs go even further - this will cause the program to die because of this:
use warnings FATAL => 'all';
You are comparing variables using eq, which means you are doing a string comparison. A string comparison expects two strings, but you are providing an undefined variable (variable declared, but not defined, so not a string). This is not clean because you are using that operator with invalid input. If you wanted to know if the variables differ, not just the strings they (may or may not) represent, you would not use a string comparison like that.
It works because Perl knows that you want to compare strings (eq) so it assumes you don't care about the fact that a variable has no value assigned. The undefined variable is converted into an empty string (temporarily), which is then compared. (Actually, the variable itself isn't converted, it's still undef after the comparison, but that's not important.)
Of course, this assumption could be wrong and there might be a bug in your code. So it'd be better to check for invalid input before comparing it.
You don't care about the difference between undef and '' (and you know why).
You could explicitly compare empty strings instead of undef. Another programmer who is reading your code will know what's going on (won't assume there's a bug).
if (($var1 // q()) eq ($var2 // q()))
...
In many cases, you might actually care about undef.
For example, your script might take some input (maybe a hash) and if that input variable is an empty string, that would be okay, but if it's undef (maybe not found in the input hash), that would be an error.
if (!defined($var1))
{
die "Input data missing, can't continue!";
}
if ($var1 eq $var2)
...

what does the double forward slash mean here?

I'm new to Perl and came across this piece of code at work, I search for a while but did not find the answer. Can anyone help to explain its function in plain english? thanks.
my $abc = delete $args{ 'abc' } // croak 'some information!';
From this page here: http://perldoc.perl.org/perlop.html#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 of its truth. Thus, EXPR1 // EXPR2 returns the value of EXPR1 if it's defined, otherwise, the value of EXPR2 is returned. (EXPR1 is evaluated in scalar context, EXPR2 in the context of // itself). Usually, this is the same result as defined(EXPR1) ? EXPR1 : EXPR2 (except that the ternary-operator form can be used as a lvalue, while EXPR1 // EXPR2 cannot, and EXPR1 will only be evaluated once). 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).
Check for Logical Defined-Or in perlop, it is similar to || but it checks for undef value (not false one).
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 of its truth.
So in short,
my $abc = delete $args{ 'abc' } // croak 'some information!';
will croak when $args{ 'abc' } returns undef value.

What does // and //= do in Perl?

I am new to Perl. I am still trying to learn the syntax of it. I have seen someone using // and //= in Perl but I couldn't find any resources on the web that explain this.
Can someone explain to me what exactly does it mean in layman terms? And what it actually does?
As kjprice mentioned, // is the logical 'defined or' operator and is documented here on the perlop page and the relevant excerpt is
it's exactly the same as ||, except that it tests the left hand side's definedness instead of its truth. Thus, EXPR1 // EXPR2 returns the value of EXPR1 if it's defined, otherwise, the value of EXPR2 is returned.
You can think of
my $var = EXPR1 // EXPR2;
as a short hand way of writing:
my $var;
if ( defined EXPR1 ) {
$var = EXPR1;
} else {
$var = EXPR2;
}
I often use this to either assign a default value to a variable unless a supplied by command line or config file value is supplied. Something like:
my $var = $config_version // 'foo';
The //= is a variation of this with an assignemnt mixed in. That same perlop page says this:
Modifying an assignment is equivalent to doing the assignment and then
modifying the variable that was assigned to.
For //= that means instead of writing something like
my $var = EXPR1 // EXPR2;
You could write
my $var = EXPR1;
$var //= EXPR2;
and get equivalent values.
From the perldoc perlop:
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 of its truth. Thus, EXPR1 // EXPR2 returns the value of EXPR1 if it's defined, otherwise, the value of EXPR2 is returned. (EXPR1 is evaluated in scalar context, EXPR2 in the context of // itself). Usually, this is the same result as defined(EXPR1) ? EXPR1 : EXPR2 (except that the ternary-operator form can be used as a lvalue, while EXPR1 // EXPR2cannot). 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).
So:
$NODEFINED // $DEFINED # will return the value of defined
$DEFINED1 // $DEFINED2 # will return the value of $DEFINED1
$a //= $b;
is shorthand for:
$a = $a // $b;
So $a will be set to the value $b ONLY if $a is undefined.
The $a //= 42; form is useful for setting a default for a variable that may not yet be defined.

Meaning of // operator in perl

I am new to perl. Can anyone please explain the meaning of // operator in perl.
It's the definedness operator. The expression:
A // B
will return A if it's defined, otherwise B.
It's very useful for getting default values if the source of the information is not defined, with things like:
$actualBalance = $balanceFromBank // 0;
or:
$confirmation = $userInput // "N";
See the relevant part of the perlop page for more detail and make a link of perlop for future reference, since Google searches and the punctuational Perl code don't mix that well :-)
The // operator is a logical defined-or. Perlop says:
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 of its
truth. Thus, EXPR1 // EXPR2 returns the value of EXPR1 if it's
defined, otherwise, the value of EXPR2 is returned. (EXPR1 is
evaluated in scalar context, EXPR2 in the context of // itself).
Usually, this is the same result as defined(EXPR1) ? EXPR1 : EXPR2
(except that the ternary-operator form can be used as a lvalue, while
EXPR1 // EXPR2 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) .
In short: It returns the left side if that expression is defined (as in not undef), or the right side.
my $foo = undef;
say $foo // 42;
# 42
my $bar = 'bar';
say $bar // 42;
# bar
It's so called defined-or operator, which has been implemented in Perl 5.10. Example from the doc:
The following expression:
$a // $b
... is merely equivalent to
defined $a ? $a : $b
And the statement:
$c //= $d;
... can now be used instead of
$c = $d unless defined $c;
Here's how || and // are different:
use 5.010;
my $rabbits = 0;
say $rabbits || 1; # 1, as 0 || 1 evaluates to 1
say $rabbits // 1; # 0, as 0 is not `undef`
That is "defined-or". $abc // "default" is equivalent to defined($abc) ? $abc : "default". Meaning if the left side of // has a defined value then that value is used, otherwise the right side of it.
See "Logical defined-or" in the perlop man page.
is defined or
like,
my $a //= 3;
will assign 3 to $a
it is different from ||, which is simply, or in that:
my $a = "";
$a //= 3;
print "|$a|\n";
$a = "";
$a ||=5;
print "|$a|\n";
will print only |5|, because in the first case $a is defined (with a false value), while in the second it matters if $a evaluates to true or not.

Why does // have lower precedence than equality in perl?

Why does // have lower precedence than == in (at least) perl 5.010?
For example, this
use 5.010;
my $may_be_undefined = 1;
my $is_equal_to_two = ($may_be_undefined//0 == 2);
say $is_equal_to_two;
prints (for me) very unexpected result.
It's because of the category of operators which // falls under, aswell as ==.
== is an "equality operator" though // falls under the category of "C-style logical operators".
As an example; && is in the same "category" as //, with that said both of the statements below are equivalent when it comes to operator precedence. That might make it easier to understand?
print "hello world" if $may_be_undefined && 0 == 2;
print "hello world" if $may_be_undefined // 0 == 2;
Documentation of 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 of its truth.
Thus, $a // $b is similar to defined($a) || $b (except 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 evaluated (unlike C's || and &&, which return 0 or 1).
Documentation of Operator Precedence and Associativity