How to use a Perl global hash - perl

I'm having a problem with Perl. It's giving me an error that I don't understand.
This is my program
our $neighbor = {};
$$neighbor{'a'} = 'b';
print Dumper($vizinho);
sub keyboard{
my ($a,$b) = #_;
return 4 if ($a eq $b);
return 2 if $neighbor{$a}{$b};
return -1;
}
And my error is
Variable "%vizinho" is not imported at t/DistStr.t line 30.
Global symbol "%vizinho" requires explicit package name at t/DistStr.t line 30.
Execution of t/DistStr.t aborted due to compilation errors.
# Looks like your test exited with 255 just after 1.
What I want to do is
use Alinhamento;
$neighbor = ... # Something which will create an hash where
# $neighbor{$x}{$y} exists if the letter $x is neighbour of $y
sub keyboard {
my ($a, $b) = #_;
return 4 if ($a eq $b);
return 2 if $neighbor{$a}{$b}; #And use that $neighbor on that function
return -1;
}
But I don't know how to make that. May I have some advice please?

There are a number of approaches, depending on specifics that are not apparent in the context provided. Here is one simple approach loosely based on your original posting:
use Data::Dumper;
our %neighbor;
$neighbor{'a'}{'b'} = 1;
print Dumper(\%neighbor);
sub keyboard{
my ($a, $b) = #_;
return 4 if ($a eq $b);
return 2 if $neighbor{$a}{$b};
return -1;
}
EDIT: Renamed $vizinho to %neighbor. Thanks #Borodin.
Note $a and $b are a little special in Perl. See the documentation for sort.

You must start every Perl program with
use strict;
use warnings;
and many problems will resolve themselves.
You use package (global) variables in the same way as any other variable. In fact, if you have been used to not using strict, then all of your variables have probably been package variables.
Update
To set element x, y of your hash so that it exists and is true, you should write
$vizinho->{$x}{$y} = 1;
Your problem seems to be with how to use references. You declare
our $vizinho = {}
and then try to assign to it using
$$vizinho{'a'} = 'b'
which is wrong. You could write
${$vizinho}{'a'} = 'b'
or, much better
$vizinho->{a} = 'b'
You also shouldn't ever use $a or $b. Your code should look like this
use strict;
use warnings;
our $vizinho = {};
$vizinho->{a} = 'b';
sub keyboard {
my ($meu_a, $meu_b) = #_;
return 4 if $meu_a eq $meu_b;
return 2 if $vizinho->{$meu_a} eq $meu_b;
return -1;
}

With the below line you create a scalar to a hash reference:
our $neighbor = {};
What I suspect you want is just a hash
our %neighbor = (
'foo' => {
'bar' => 1,
},
'biz' => {
'baz' => 1,
},
);
sub keyboard {
my ($key1, $key2) = #_;
return 4 if ($key1 eq $key2);
return 2 if $neighbor{$key1}{$key2}; #And use that $neighbor on that function
return -1;
}
Also note that $a and $b are special variables used by perl's sort function, so it's probably best to use another variable name for clarity.

Related

You can't assign Perl $_ to a hash in a foreach statement

I have tried everything I can think of (plus a tonne of random experiments) to assign $_ within the foreach statement to a hash. I know that you can assign it after the foreach line, but I have a very particular code limitation which doesn't allow me to do this.
#!/usr/bin/perl -s
use strict;
use Data::Dumper;
my #x = qw(a c e g);
my $var = {'a'=>"z", 'b'=>"y", 'c'=>"x", 'd'=>"w", 'e'=>"v", 'f'=>"u", 'g'=>"t", 'h'=>"s"};
my $y = "e";
foreach $var->{$y} (#x){
print "$y = $var->{$y}\n";
$y = $var->{$y};
}
What I think is happening is the perl compiler cannot handle '{' and '}' characters in the position where it is looking for $VAR to assign $_ to. When I run the code not only do I get an error about the foreach line, but I also get a syntax error about the print line where there is no syntax error.
syntax error at ./foreach2var.pl line 9, near "$var->"
syntax error at ./foreach2var.pl line 12, near "}"
Execution of ./foreach2var.pl aborted due to compilation errors.
Is there any way to assign $_ within the foreach statement directly to a hash reference rather than assigning it with $var->{$y} = $_; on the following line?
I am looking for the following output
e = a
a = c
c = e
e = g
Also, I am aware that the following works, but again, I have a particular code limitation which means I have to be able to handle foreach statements
#!/usr/bin/perl -s
use strict;
use Data::Dumper;
my #x = qw(a c e g);
my $var = {'a'=>"z", 'b'=>"y", 'c'=>"x", 'd'=>"w", 'e'=>"v", 'f'=>"u", 'g'=>"t", 'h'=>"s"};
my $y = "e";
while($var->{$y} = shift #x){
print "$y = $var->{$y}\n";
$y = $var->{$y};
}
From Foreach Loops in perlsyn
The foreach loop iterates over a normal list value and sets the scalar variable VAR to be each element of the list in turn.
Thus, it needs a variable and the dereferenced computed-on-the-fly value you'd like to assign to isn't even an lvalue, much less a variable.
How strict is this "variable" requirment? The rest of that paragraph goes
If the variable is preceded with the keyword my, then it is lexically scoped, and is therefore visible only within the loop. Otherwise, the variable is implicitly local to the loop and regains its former value upon exiting the loop. If the variable was previously declared with my, it uses that variable instead of the global one, but it's still localized to the loop. This implicit localization occurs only in a foreach loop.
So we do need a variable there. The requirement is purely syntactical though.†
I'm not sure what precisely you need to do and what your restrictions are but
for (#x) {
$var->{$y} = $_;
...
}
does indeed assign as desired, as observed in the question.
Having it assigned as a topicalizer, for $v (#ary) { }, does have the extra property of localizing $v within the loop, as quoted above from docs, but you don't seem to need that part.
† One can localize parts of a complex structure. A command-line program
perl -Mstrict -wE'
my $hr = { k => 2 }; say $hr->{k};
SAVE: { local $hr->{k} = 7; say $hr->{k} };
say $hr->{k}'
prints lines 2, 7, 2.
No. As per the documentation, it must be a variable.
It really doesn't make sense for it to be anything else because the variable's value is restored at the end of the loop.
$_ = "abc";
say;
for (qw( def ghi )) {
say;
}
say;
Output:
abc
def
ghi
abc
You can get the desired output from each of the following:
my $prev = "e";
while ( #x ) {
my $this = shift( #x );
say "$prev = $this";
$prev = $this;
}
my $prev = "e";
for my $this ( #x ) {
say "$prev = $this";
$prev = $this;
}
my $this = "e";
while ( #x ) {
( my $prev, $this ) = ( $this, shift( #x ) );
say "$prev = $this";
}
unshift #x, "e";
for my $i ( 1 .. $#x ) {
say "$x[ $i - 1 ] = $x[ $i ]";
}

How do you lock a member variable in perl?

I wrote a script in perl which does multi-threading, I then tried to convert it over into an object. However, I can't seem to figure out how to lock on a member variable. The closest I've come to is:
#!/usr/bin/perl
package Y;
use warnings;
use strict;
use threads;
use threads::shared;
sub new
{
my $class = shift;
my $val :shared = 0;
my $self =
{
x => \$val
};
bless $self, $class;
is_shared($self->{x}) or die "nope";
return $self;
}
package MAIN;
use warnings;
use strict;
use threads;
use threads::shared;
use Data::Dumper;
my $x = new Y();
{
lock($x->{x});
}
print Dumper('0'); # prints: $VAR = '0';
print Dumper($x->{x}); # prints: $VAR = \'0';
print "yes\n" if ($x->{x} == 0); # prints nothing
#print "yes\n" if ($$x->{x} == 0); # dies with msg: Not a SCALAR reference
my $tmp = $x->{x}; # this works. Must be a order of precedence thing.
print "yes\n" if ($$tmp == 0); # prints: yes
#++$$x->{x}; # dies with msg: Not a SCALAR reference
++$$tmp;
print Dumper($x->{x}); # prints: $VAR = \'1';
This allows me to put a lock on the member var x, but it means I'd be needing 2 member variables as the actual member var isn't really capable of being manipulated by assigning to it, incrementing it, etc. I can't even test against it.
EDIT:
I'm thinking that I should rename this question "How do you dereference a member variable in perl?" as the problem seems to boil down to that. Using $$x->{x} is invalid syntax and you can't force precedence rules with parentheses. I.e. $($x->{x}) doesn't work. Using a temporary works but it a nuisance.
I don't get what you are trying to do with threads and locking, but there are some simple errors in the way you use references.
$x->{x}
is a reference to a scalar, so the expressions
$x->{x} == 0
++$$x->{x}
both look suspect. $$x->{x} is parsed as {$$x}->{x} (dereference $x, then treat it as a hash reference and look up the value with key x). I think you mean to say
${$x->{x}} == 0
++${$x->{x}}
where ${$x->{x}} means to treat $x as a hash reference, to look up the value for key x in that hash, and then to dererence that value.

Perl custom syntax for passing function arguments

I have been using perl for some time now.
I want to know how I can run the following operation in perl:
subtract(40)(20)
To get the result:
20
I think I would have to look at custom parsing techniques for Perl.
This is what I am looking at right now:
Devel::Declare
Devel::CallParser
and
http://www.perl.com/pub/2012/10/an-overview-of-lexing-and-parsing.html
Now, I am not sure what to look for or what to do.
Any help on HOW to go about this, WHAT to read would be appreciated. Please be clear.
Thank you.
I recommend trying Parse::Keyword. Parse::Keyword is really great for parsing custom syntax, as it lets you call back various parts of the Perl parser, such as parse_listexpr, parse_block, parse_fullstmt, etc (see perlapi).
It has a drawback in that if you use those to parse expressions that close over variables, these are handled badly, but this can be worked around with PadWalker.
Parse::Keyword (including PadWalker trickery) is what Kavorka uses; and that does some pretty complex stuff! Early versions of p5-mop-redux used it too.
Anyway, here's a demonstration of how your weird function could be parsed...
use v5.14;
use strict;
use warnings;
# This is the package where we define the functions...
BEGIN {
package Math::Weird;
# Set up parsing for the functions
use Parse::Keyword {
add => \&_parser,
subtract => \&_parser,
multiply => \&_parser,
divide => \&_parser,
};
# This package is an exporter of course
use parent 'Exporter::Tiny';
our #EXPORT = qw( add subtract multiply divide );
# We'll need these things from PadWalker
use PadWalker qw( closed_over set_closed_over peek_my );
sub add {
my #numbers = _grab_args(#_);
my $sum = 0;
$sum += $_ for #numbers;
return $sum;
}
sub subtract {
my #numbers = _grab_args(#_);
my $diff = shift #numbers;
$diff -= $_ for #numbers;
return $diff;
}
sub multiply {
my #numbers = _grab_args(#_);
my $product = 1;
$product *= $_ for #numbers;
return $product;
}
sub divide {
my #numbers = _grab_args(#_);
my $quotient = shift #numbers;
$quotient /= $_ for #numbers;
return $quotient;
}
sub _parser {
lex_read_space;
my #args;
while (lex_peek eq '(')
{
# read "("
lex_read(1);
lex_read_space;
# read a term within the parentheses
push #args, parse_termexpr;
lex_read_space;
# read ")"
lex_peek eq ')' or die;
lex_read(1);
lex_read_space;
}
return sub { #args };
}
# In an ideal world _grab_args would be implemented like
# this:
#
# sub _grab_args { map scalar(&$_), #_ }
#
# But because of issues with Parse::Keyword, we need
# something slightly more complex...
#
sub _grab_args {
my $caller_vars = peek_my(2);
map {
my $code = $_;
my $closed_over = closed_over($code);
$closed_over->{$_} = $caller_vars->{$_} for keys %$closed_over;
set_closed_over($code, $closed_over);
scalar $code->();
} #_;
}
# We've defined a package inline. Mark it as loaded, so
# that we can `use` it below.
$INC{'Math/Weird.pm'} = __FILE__;
};
use Math::Weird qw( add subtract multiply );
say add(2)(3); # says 5
say subtract(40)(20); # says 20
say multiply( add(2)(3) )( subtract(40)(20) ); # says 100
If you can live with the additions of a sigil and an arrow, you could curry subtract as in
my $subtract = sub {
my($x) = #_;
sub { my($y) = #_; $x - $y };
};
Call it as in
my $result = $subtract->(40)(20);
If the arrow is acceptable but not the sigil, recast subtract as
sub subtract {
my($x) = #_;
sub { my($y) = #_; $x - $y };
};
Invocation in this case looks like
my $result = subtract(40)->(20);
Please don't tack on broken syntax extensions on your program to solve a solved problem.
What you want are closures, and a technique sometimes called currying.
Currying is the job of transforming a function that takes multiple arguments into a function that is invoked multiple times with one argument each. For example, consider
sub subtract {
my ($x, $y) = #_;
return $x - $y;
}
Now we can create a subroutine that already provides the first argument:
sub subtract1 { subtract(40, #_) }
Invoking subtract1(20) now evaluates to 20.
We can use anonymous subroutines instead, which makes this more flexible:
my $subtract = sub { subtract(40, #_) };
$subtract->(20);
We don't need that variable:
sub { subtract(40, #_) }->(20); # equivalent to subtract(40, 20)
We can write subtract in a way that does this directly:
sub subtract_curried {
my $x = shift;
# don't return the result, but a subroutine that calculates the result
return sub {
my $y = shift;
return $x - $y;
};
}
Now: subtract_curried(40)->(20) – notice the arrow in between, as we are dealing with a code reference (another name for anonymous subroutine, or closures).
This style of writing functions is much more common in functional languages like Haskell or OCaml where the syntax for this is prettier. It allows very flexible combinations of functions. If you are interested in this kind of programming in Perl, you might want to read Higher-Order Perl.
#Heartache: Please forget this challenge as it makes no sense for the parser and the user.
You can think of using fn[x][y] or fn{x}{y} which are valid syntax variants - i.e. you can stack [] and {} but not lists,
or fn(x,y) or fn(x)->(y) which do look nice, are also valid and meaningful syntax variants.
But fn(x)(y) will not know in which context the second list should be used.
For fn(x)(y) the common interpretation would be fn(x); (y) => (y). It returns the 2nd list after evaluating the first call.
You may create the source code filter:
package BracketFilter;
use Filter::Util::Call;
sub import {
filter_add(sub {
my $status;
s/\)\(/, /g if ($status = filter_read()) > 0;
return $status ;
});
}
1;
And use it:
#!/usr/bin/perl
use BracketFilter;
subtract(40)(20);
sub subtract {
return $_[0] - $_[1];
}

Exploring the uses of anonymous subs

I've always been somewhat confused about the purpose and usage of anonymous subs in perl. I understand the concept, but looking for examples and explanations on the value of this practice.
To be clear:
sub foo { ... } # <--- named sub
sub { ... } # <--- anonymous sub
For example:
$ perl -e 'print sub { 1 }'
CODE(0xa4ab6c)
Tells me that sub returns a scalar value. So, I can do:
$ perl -e '$a = sub { 1 }; print $a'
For the same output as above. This of course holds true for all scalar values, so you can load arrays or hashes with anonymous subs.
The question is, how do I use these subs? Why would I want to use them?
And for a gold star, is there any problem which can only be resolved with an anonymous sub?
Anonymous subroutines can be used for all sorts of things.
Callbacks for event handling systems:
my $obj = Some::Obj->new;
$obj->on_event(sub {...});
Iterators:
sub stream {my $args = \#_; sub {shift #$args}}
my $s = stream 1, 2, 3;
say $s->(); # 1
say $s->(); # 2
Higher Order Functions:
sub apply (&#) {
my $code = shift;
$code->() for my #ret = #_;
#ret
}
my #clean = apply {s/\W+/_/g} 'some string', 'another string.';
say $clean[0]; # 'some_string'
Creating aliased arrays:
my $alias = sub {\#_}->(my $x, my $y);
$alias[0]++;
$alias[1] = 5;
say "$x $y"; # '1 5''
Dynamic programming with closures (such as creating a bunch of subroutines that only differ by a small amount):
for my $name (qw(list of names)) {
no strict 'refs';
*$name = sub {... something_with($name) ...};
}
There is no situation where an anonymous subroutine can do anything that a named subroutine can not. The my $ref = sub {...} constructor is equivalent to the following:
sub throw_away_name {...}
my $ref = \&throw_away_name;
without having to bother with deciding on a unique 'throw_away_name' for each sub.
The equivalence also goes the other way, with sub name {...} being equivalent to:
BEGIN {*name = sub {...}}
So other than the name, the code reference created by either method is the same.
To call a subroutine reference, you can use any of the following:
$code->(); # calls with no args
$code->(1, 2, 3); # calls with args (1, 2, 3)
&$code(); # calls with no args
&$code; # calls with whatever #_ currently is
You can even use code references as methods on blessed or unblessed scalars:
my $list = sub {#{ $_[0] }};
say for [1 .. 10]->$list # which prints 1 .. 10
You can use it to create iterators.
use strict;
use warnings;
use 5.012;
sub fib_it {
my ($m, $n) = (0, 0);
return sub {
my $val = ( $m + $n );
$val = 1 unless $val;
($m, $n) = ($n, $val);
return $val;
}
}
my $fibber = fib_it;
say $fibber->() for (1..3); ### 1 1 2
my $fibber2 = fib_it;
say $fibber2->() for (1..5); ### 1 1 2 3 5
say $fibber->() for (1..3); #### 3 5 8
Anonymous subroutines can be used to create closures.
Closure is a notion out of the Lisp world that says if you define an anonymous function in a particular lexical context, it pretends to run in that context even when it's called outside the context.
perlref
What's a closure?
Here's something similar you might have seen before:
#new_list = map { $_ + 1 } #old_list;
And also:
#sorted = sort { $a <=> $b } #unsorted;
Neither of those are anonymous subs, but their behavior can be imitated in your functions with anonymous subs. They don't need the sub keyword because the functions are (essentially) prototyped to have their first argument be a subroutine, and Perl recognizes that as a special case where sub can be left off. (The functions also set the requisite variables to meaningful values before calling the subroutines you provided in order to simplify argument passing, but that's not related.)
You can write your own map-like function:
sub mapgrep (&#) { # make changes and also filter based on defined-ness
my ($func, #list) = #_;
my #new;
for my $i (#list) {
my $j = $func->($i);
push #new, $j if defined $j;
}
}
The magic to make it work with $_ is a bit much to write here - the above version only works for subs that take arguments.
Well I wrote a SAX parser for perl that is event driven. You can pass anonymous subs to the begin/end events on an element.
my $str = "<xml><row><data></data></row></xml>":
my $parser = SAXParser->new();
$parser->when('row')->begin(sub {
my ($element) = #_;
push(#rows, $row);
});
$parser->when('row')->end(sub {
## do something like serialize it or whatever
});
$parser->parse($str);
They are generally used when you want to pass a sub to another bit of code. Often this is a case of "When X happens (in third party code) do Y".
For example. When defining an attribute in Moose, you can specify the default value of that attribute using a sub. Given a class which has, as part of its definition:
has 'size' => (
is => 'ro',
default =>
sub { ( 'small', 'medium', 'large' )[ int( rand 3 ) ] },
predicate => 'has_size',
);
Whenever an instance of that class is created without an explicit size being passed, the sub will be called and the return value will be the size for that object.
If we switch to another language to give a different example, you'll find a similar concept in JavaScript.
var b = document.getElementById('my_button').
b.addEventListener('click', function (e) { alert('clicked!'); });
In your example, you haven't actually called created subroutine. Call is performed with either &$a or $a->() syntax. What you've done is that you stored a reference to subroutine in $a, then stringifyed it and printed result. Compare:
my $a = sub {1};
my $b = sub {1};
print join("\n", $a, $a->(), $b, $b->());
These are subs for the lazy programmer. You can use them for local throw-away functions and can save some typing. Instead of
sub x { ... }
my $function_ptr = \&x;
you can now use
my $function_ptr = sub { ... };
The anonymous functions are also private, and can only be accessed through the $function_ptr, so they don't have an entry in the symbol table.

How to check if several variables are empty in Perl

I have a Perl script where variables must be initialized before the script can proceed. A lengthy if statement where I check each variable is the obvious choice. But maybe there is a more elegant or concise way to check several variables.
Edit:
I don't need to check for "defined", they are always defined with an empty string, I need to check that all are non-empty.
Example:
my ($a, $b, $c) = ("", "", "");
# If-clauses for setting the variables here
if( !$a || !$b || !$c) {
print "Init failed\n";
}
I am assuming that empty means the empty string, not just any false value. That is, if 0 or "0" are ever valid values post-initialization, the currently accepted answer will give you the wrong result:
use strict; use warnings;
my ($x, $y, $z) = ('0') x 3;
# my ($x, $y, $z) = ('') x 3;
for my $var ($x, $y, $z) {
die "Not properly initialized\n" unless defined($var) and length $var;
}
Now, this is pretty useless as a validation, because, more than likely, you would like to know which variable was not properly initialized if this situation occurs.
You would be better served by keeping your configuration parameters in a hash so you can easily check which ones were properly initialized.
use strict; use warnings;
my %params = (
x => 0,
y => '',
z => undef,
);
while ( my ($k, $v) = each %params ) {
validate_nonempty($v)
or die "'$k' was not properly initialized\n";
}
sub validate_nonempty {
my ($v) = #_;
defined($v) and length $v;
}
Or, if you want to list all that were not properly initialized:
my #invalid = grep is_not_initialized($params{$_}), keys %params;
die "Not properly initialized: #invalid\n" if #invalid;
sub is_not_initialized {
my ($v) = #_;
not ( defined($v) and length $v );
}
use List::MoreUtils 'all';
say 'Yes' if (all { defined } $var1, $var2, $var3);
What do you mean by "initialized"? Have values that are not "undef"?
For a small amount of values, the straightforward if check is IMHO the most readable/maintainable.
if (!$var1 || !$var2 || !$var3) {
print "ERROR: Some are not defined!";
}
By the way, checking !$var is a possible bug in that "0" is false in Perl and thus a string initialized to "0" would fail this check. It's a lot better to use $var eq ""
Or better yet, space things out for >3 values
if (!$var1 # Use this if your values are guarantee not to be "0"
|| $var2 eq "" # This is a LOT better since !$var fails on "0" value
|| $var3 eq "") {
print "ERROR: Some are not defined!";
}
If there are so many values to check that the above becomes hard to read (though with per-line check as in the second example, it doesn't really ever happen), or if the values are stored in an array, you can use grep to abstract away the checking:
# We use "length" check instead of "$_ eq ''" as per tchrist's comment below
if (grep { length } ($var1, $var2, $var3, $var4, $var5, #more_args) ) {
print "ERROR: Some are not defined!";
}
If you must know WHICH of the values are not defined, you can use for loop (left as an obvious excercise for the reader), or a map trick:
my $i = -1; # we will be pre-incrementing
if (my #undefined_indexes = map { $i++; $_ ? () : $i }
($var1, $var2, $var3, $var4, $var5, #more_args) ) {
print "ERROR: Value # $_ not defined!\n" foreach #undefined_indexes;
}
use List::Util 'first';
if (defined first { $_ ne "" } $a, $b, $c) {
warn "empty";
}
Your way is readable and easy to understand which means it's easy to maintain. Restating your boolean using de Morgan's laws:
if (not($a and $b and $c)) {
warn(qq(Not all variables are initialized!))
}
That way, you're not prefixing not in front of every variable, and it doesn't affect readability. You can use List::Util or List::MoreUtils, but they don't really add to the legibility.
As Sinan Ünür stated, if you put the variables in a hash, you could parse through the hash and then list which variables weren't initialized. This might be best if there are a lot of these variables, and the list keeps changing.
foreach my $variable qw(a b c d e f g h i j) {
if (not $param{$variable}) {
warn qq(You didn't define $variable\n);
}
}
You can use Getopts::Long to put your parameter values inside a hash instead of separate variables. Plus, the latest versions of Getopts::Long can now operate on any array and not just #ARGV.