bash operator for logical defined-or - perl

Is there an equivalent Bash operator to Perl's logical defined-or? Something akin to:
$a = $a // $b;
OR
$a ||= $b;

"Assign Default Values" parameter expansion.
echo "${foo:=42}"

Related

what is the usage of \& and $expr->()

sub reduce(&#) {
my $expr = \&{shift #ARG};
my $result = shift #ARG;
while (scalar #ARG > 0) {
our $a = $result;
our $b = shift #ARG;
$result = $expr->();
}
return $result;
}
I cannot really understand some grammar in this code. Anyone can explain to me? like \& and $result = $expr->()
\&name returns a reference to the subroutine named name.
$code_ref->() calls the subroutine referenced by $code_ref.
$ perl -e'
sub f { CORE::say "Hi" }
my $code_ref = \&f;
$code_ref->();
'
Hi
In your case, shift #ARG returns a subroutine reference. \&{ $code_ref } simply returns the code ref. As such,
my $expr = \&{shift #ARG};
could have been written as
my $expr = shift #ARG;
Note that reduce's prototype allows it to be called as
reduce { ... } ...
but what is actually executed is
reduce( sub { ... }, ... )
Note that this version of reduce is buggy. You should use the one provided by List::Util.
local $a and local $b should have been used to avoid clobbering the values its caller might have in $a and $b.
This version of reduce expects its callback to have been compiled in the same package as reduce itself. Otherwise, the callback sub won't be able to simply use $a and $b.
Declaring the variables using our is actually completely useless in this version case since $a and $b are exempt from use strict; checks, and the undeclared use of $a and $b would access the very same package variables.
Having a look some List::Util::reduce() examples will probably help.
Let's take the first one:
$foo = reduce { $a > $b ? $a : $b } 1..10;
So reduce takes a BLOCK followed by a LIST, which the function signature declares: sub reduce(&#) {. The block in our case is the statement $a > $b ? $a : $b, while the list is 1..10. From the docs:
Reduces #list by calling "BLOCK" in a scalar context multiple times,
setting $a and $b each time. The first call will be with $a and $b set to
the first two elements of the list, subsequent calls will be done by
setting $a to the result of the previous call and $b to the next element
in the list.
Returns the result of the last call to the "BLOCK". If #list is empty then
"undef" is returned. If #list only contains one element then that element
is returned and "BLOCK" is not executed.
And now to an annotated version of the code:
$foo = reduce { $a > $b ? $a : $b } 1..10; # $foo will be set to 10
sub reduce(&#) {
# reduce() takes a BLOCK followed by a LIST
my $expr = \&{shift #ARG};
# $expr is now a subroutine reference, i.e.
# $expr = sub { $a > $b ? $a : $b };
# Start by setting $result to the first item in the list, 1
my $result = shift #ARG;
# While there are more items in the list...
while (scalar #ARG > 0) {
# Set $a to the current result
our $a = $result;
# Set $b to the next item in the list
our $b = shift #ARG;
# Set $result to the result of $a > $b ? $a : $b
$result = $expr->();
}
# List has now been reduced by the operation $a > $b ? $a : $b
return $result;
}

Perl code is not throwing any error

#!/usr/bin/perl
use strict ;
$b = 5;
my $var=10;
print $var;
Above code is not throwing error. I have not used my for variable $b.
$b is a predeclared variable in Perl. It is used with sort() like so:
my #sorted = sort { $a <=> $b } #list;
It is documented in perldoc perlvar.

Can I pass arguments to the compare subroutine of sort in Perl?

I'm using sort with a customized comparison subroutine I've written:
sub special_compare {
# calc something using $a and $b
# return value
}
my #sorted = sort special_compare #list;
I know it's best use $a and $b which are automatically set, but sometimes I'd like my special_compare to get more arguments, i.e.:
sub special_compare {
my ($a, $b, #more) = #_; # or maybe 'my #more = #_;' ?
# calc something using $a, $b and #more
# return value
}
How can I do that?
Use the sort BLOCK LIST syntax, see perldoc -f sort.
If you have written the above special_compare sub, you can do, for instance:
my #sorted = sort { special_compare($a, $b, #more) } #list;
You can use closure in place of the sort subroutine:
my #more;
my $sub = sub {
# calc something using $a, $b and #more
};
my #sorted = sort $sub #list;
If you want to pass the elements to be compared in #_, set subroutine's prototype to ($$). Note: this is slower than unprototyped subroutine.

Is there a Perl idiom which is the functional equivalent of calling a subroutine from within the substitution operator?

Perl allows ...
$a = "fee";
$result = 1 + f($a) ; # invokes f with the argument $a
but disallows, or rather doesn't do what I want ...
s/((fee)|(fie)|(foe)|(foo))/f($1)/ ; # does not invoke f with the argument $1
The desired-end-result is a way to effect a substitution geared off what the regex matched.
Do I have to write
sub lala {
my $haha = shift;
return $haha . $haha;
}
my $a = "the giant says foe" ;
$a =~ m/((fee)|(fie)|(foe)|(foo))/;
my $result = lala($1);
$a =~ s/$1/$result/;
print "$a\n";
See perldoc perlop. You need to specify the e modifier so that the replacement part is evaluated.
#!/usr/bin/perl
use strict; use warnings;
my $x = "the giant says foe" ;
$x =~ s/(f(?:ee|ie|o[eo]))/lala($1)/e;
print "$x\n";
sub lala {
my ($haha) = #_;
return "$haha$haha";
}
Output:
C:\Temp> r
the giant says foefoe
Incidentally, avoid using $a and $b outside of sort blocks as they are special package scoped variables special-cased for strict.

Why doesn't Perl's strictures complain about an undeclared $a?

Why is there no error issued by strict:
use strict;
$a = $a + 1;
$a and $b are special globals used by sort, so they're always defined. Try it with $c instead and you will get an error.
Although strict does not complain about the special $a and $b variables,
perlcritic will detect their usage:
Magic variables should be assigned as
"local"... (Severity: 4)
$a is a special global variable. It doesn't need to be declared. See perldoc perlvar.
In Perl there are some global variables. Here $a and $b are used in the sort function.
I think you might have noticed, like in this statement:
sort { $a <=> $b } #array_name ;