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

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 ;

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.

bash operator for logical defined-or

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}"

Does my $_; do anything if $_ is implied

I think the answer is yes but I just want to make sure. so if I have
sub something {
my $_;
my #array = ...;
while ( #array ) {
say;
}
}
is the my $_; actually effective at lexicalizing the parameter passed to the say?
In this particular case I'm using the DZP::UnusedVarsTests and it's complaining that I haven't used my $_; and I suspect it's a bug since I'm using it in a case where it's implied.
The short answer is Yes. It makes the functions in that scope use the lexically scoped $_, and not the global $_. If they write back to $_, as in the case of s///, you will have some level of damage control.
Per perldoc perldelta (5.10.0):
"List::Util::first" misbehaves in the presence of a lexical $_ (typically introduced by "my $_" or implicitly by "given"). The variable which gets set for each iteration is the package variable $_, not the lexical $_ [RT #67694].
A similar issue may occur in other modules that provide functions which take a block as their first argument, like
foo { ... $_ ...} list
And, in perldoc perl591delta it goes on to say:
Lexical $_
The default variable $_ can now be lexicalized, by declaring it like
any other lexical variable, with a
simple
my $_;
The operations that default on $_ will use the lexically-scoped version of $_ when it exists, instead of the global $_.
In a "map" or a "grep" block, if $_ was previously my'ed, then the $_ inside the block is lexical as well (and scoped to the block).
In a scope where $_ has been lexicalized, you can still have access to the global version of $_ by using $::_, or, more simply, by overriding the lexical declaration with "our $_".
Examples
I wanted to provide some examples of why this functionality would be used:
my $_ = 'BOOM!';
sub something {
my $_; ## Try running with and without
my #array = qw/foo bar baz/;
while ( $_ = pop #array ) {
say;
}
}
something();
say;
And, another example
my $_ = 'foo';
sub something {
my $_ = $_; ## Try running with and without
s/foo/bar/;
$_;
}
something();
say;

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.