My question in Perl is:
Define 2x2 arrays using anonymous lists. Pass the arrays to a subroutine and add them together. Return a reference to sum array and print the values from the main part of the program.
My script is:
#!/usr/bin/perl
use strict;
use warnings;
my #array = ([1,2],[4,5]);
my $refarray = \#array;
print sumarray($refarray);
sub sumarray
{
$refarray = shift;
foreach (#{$refarray})
{
$refarray = ($refarray[0]->[0]+$refarray[1]->[0],$refarray[0]->[1]+$refarray[1]->[1]);
}
return $refarray;
}
Where am I going wrong? Please help. Thanks in advance.
I am getting the output as 0.
If I use use strict; and use warnings; I will get the error message as
Global symbol "#refarray" requires explicit package name at line 23.
Global symbol "#refarray" requires explicit package name at line 23.
Global symbol "#refarray" requires explicit package name at line 23.
Global symbol "#refarray" requires explicit package name at line 23.
Execution aborted due to compilation errors.
Few problems with your code: -
First, in your for-loop, you are modifying your reference $refarray which you should not do.
Second, $refarray[0]->[0] will not compile. Since $refarray is a reference to an array, you should either use its 1st element using arrow: - $refarray->[0][0], or you need to de-reference it before using the way you are using: - $$refarray[0]->[0].
Having said that, I think you should replace your subroutine with this one: -
use strict;
use warnings;
my #array = ([1,2],[4,5]);
my $refarray = \#array;
my $sum = sumarray($refarray);
print $sum->[0], $sum->[1];
sub sumarray {
my $ref = shift;
return [$ref->[0][0] + $ref->[1][0], $ref->[0][1] + $ref->[1][1]];
}
OUTPUT: -
5 7
Try this:
#!/usr/bin/perl -w
my $r = sumarray([1,2],[3,4]);
print $r->[0], " ", $r->[1], "\n";
sub sumarray {
my ($a, $b) = #_;
return [
$a->[0]+$b->[0],
$a->[1]+$b->[1]
];
}
It could be expressed very simply with a combination of the list operations sum (from the core module List::Util) and map.
Code
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
use List::Util 'sum';
sub sum_square {
my #arrays = #_;
return [ map {sum #$_} #arrays ];
}
say join ', ' => #{ sum_square([1,2], [4,5]) };
Output:
3, 9
Since this is Perl, it could be expressed in a more compact way.
Shortification
sub sum_square { [ map {sum #$_} #_ ] }
say join ', ' => #{ sum_square([1,2], [4,5]) };
Shortification2
say join ', ' => map {sum #$_} [1,2], [4,5];
Edit: sum the other way round
If the function should be a column sum instead of a line sum, this modification should do the trick (iterate over the indices of the first array):
sub sum_square {
my #arrays = #_;
return [ map { my $i = $_; # $i: all indices of the first array
sum map $_->[$i] => #arrays # sum over all $i-th values of #arrays
} 0 .. $#{$arrays[0]} ];
}
Output:
5, 7
Related
Can I make different snippets of evaled Perl code share the same lexical scope and yet get their return values?
Background
Perl's eval command evaluates a string as Perl code and upon success returns the value of the last statement in that code. However, lexical variables created in that code are dropped at the end of the code. This means when eval of code1 has ended and I have a second code chunk code2, which refers to the lexical variables set in code1, this will fail.
my $code1 = 'my $c = 4';
my $code2 = 'printf "%g\n", $c;';
printf 'evaluated "%s" to %s' . "\n", $code1, eval $code1;
printf 'evaluated "%s"' . "\n", $code2;
yields
evaluated "my $c = 4" to 4
evaluated "printf "%g\n", $c;"
but not a line containing just 4 as I would wish, because $code2 should use the variable $c if lexical scopes are re-used. (I generally agree with the default that lexical scopes are constrained to only one evaled code, so I expect that some conscious modification of code is required to make the above work.)
Approaches considered
I experimented with use PadWalker qw( peek_my ); to save the lexical scope at the end of each code snippet aiming to load it into the scope of the following snippet, but then I realised that this would make inaccessible the return value of the code snippet, which is needed by the calling code.
As another alternative appears to pattern-match (probably using a dedicated parser) all my-declarations in the perl code snippets and essentially translate them on the fly, but this would amount to a considerably bigger task.
Template example for discussion (see comments)
\perlExec{
use PDL;
my $v = vpdl [ 1, 2 ];
my $w = vpdl [ 3, 4 ];
sub list ($) {
my $pdl = shift;
return join ',', map { at( $pdl, $_, 0 ) } 0..1;
}
}
The vector [ \perlValue{ list $v } ]
plus the vector [ \perlValue{ list $w } ]
makes [ \perlValue{ my $s = $v + $w; list $s } ].
Perhaps you would like to use Eval::WithLexicals? It does exactly what you are asking for. It was designed to power REPLs, and it's pure Perl. You simply make a new instance of Eval::WithLexicals, and then you call $ewl->eval($code) instead of eval $code, and the variables will persist between successive calls on the same object.
As I commented, my feeling was that this was an XY Problem in that there may be other solutions to the underlying problem. As it turns out from the discussion in the comments, you seem to be implementing your own templating system, so my first suggestion would be to have a look at existing ones, such as maybe Template::Toolkit.
If you still want to stick with your current approach, then it seems that #hobbs has given an answer that seems to answer your question directly, Eval::WithLexicals (Update: since accepted). As I mentioned, I see two other possible solutions. The first, which feels the most natural to me personally, would be to not use lexicals in the fist place. When I see the code like what you showed:
\perlExec{ my $v = [ 1, 2 ]; }
The vector [ \perlValue{ $v } ]
then, simply because of the braces, I would not be surprised that each of those has their own lexical scope. If you instead were to use package variables, it would seem more natural to me. Just for example, you could use eval qq{ package $packname; no strict "vars"; $code } (of course with the caveat that strict "vars" is disabled), or your could use fully qualified variable names ($package::v) throughout.
The second thing I mentioned was to translate the entire input file into a Perl script and eval that - in other words, write your own templating system. Although I would only recommend reinventing this wheel as your last option, you did ask how to adapt this code I wrote for your purposes, so here it is. One limitation of the following is that any braces in the code blocks must be balanced (but see update below), and since this is a somewhat simplistic demonstration, there are bound to be more limitations. Use at your own risk!
use warnings;
use strict;
use feature qw/say state/;
use Data::Dumper;
use Regexp::Common qw/balanced/;
use Capture::Tiny qw/capture_stdout/;
my $DEBUG = 1;
local $/=undef;
while (my $input = <>) {
my $code = translate($ARGV,$input);
$DEBUG and say ">>>>> Generated Code:\n", $code, "<<<<<";
my ($output, $rv) = capture_stdout { eval $code };
$rv or die "eval failed: ".($#//'unknown error');
say ">>>>> Output:\n", $output, "<<<<<";
}
sub translate {
my ($fn,$input) = #_;
state $packcnt = 1;
$fn =~ tr/A-Za-z0-9/_/cs;
my $pack = "Generated".$packcnt++."_$fn";
my $output = "{ package $pack;\n";
$output.= "no warnings; no strict;\n";
$output.= "#line 1 \"$pack\"\n";
while ( $input=~m{ \G (?<str> .*? ) \\perl(?<type> Exec|Value )
(?<code> $RE{balanced}{-parens=>'{}'} ) }xsgc ) {
my ($str,$type,$code) = #+{qw/str type code/};
$output.= "print ".perlstr($str).";\n" if length($str);
($code) = $code=~/\A\s*\{(.*)\}\s*\z/s or die $code;
$code .= ";" unless $code=~/;\s*\z/;
$code = "print do { $code };" if $type eq 'Value';
$output.= "$code\n";
}
my $str = substr $input, pos($input)//0;
$output.= "print ".perlstr($str).";\n" if length($str);
$output.= "} # end package $pack\n1;\n";
return $output;
}
sub perlstr { Data::Dumper->new([''.shift])
->Terse(1)->Indent(0)->Useqq(1)->Dump }
Input File:
\perlExec{
use warnings; use strict;
print "Hello, World\n";
my $v = [ 1, 2 ];
my $w = [ 3, 4 ];
sub list ($) {
my $pdl = shift;
return join ',', #$pdl;
}
}
The vector [ \perlValue{ list $v } ]
plus the vector [ \perlValue{ list $w } ]
makes [ \perlValue{ my $s = [#$v + #$w]; list $s } ].
Output:
>>>>> Generated Code:
{ package Generated1_input_txt;
no warnings; no strict;
#line 1 "Generated1_input_txt"
use warnings; use strict;
print "Hello, World\n";
my $v = [ 1, 2 ];
my $w = [ 3, 4 ];
sub list ($) {
my $pdl = shift;
return join ',', #$pdl;
}
;
print "\nThe vector [ ";
print do { list $v ; };
print " ]\nplus the vector [ ";
print do { list $w ; };
print " ]\nmakes [ ";
print do { my $s = [#$v + #$w]; list $s ; };
print " ].\n";
} # end package Generated1_input_txt
1;
<<<<<
>>>>> Output:
Hello, World
The vector [ 1,2 ]
plus the vector [ 3,4 ]
makes [ 4 ].
<<<<<
Update: As suggested by #HåkonHægland in the comments, it's possible to use PPR to parse out the blocks. The only changes needed are to replace use Regexp::Common qw/balanced/; by use PPR; and in the regex replace (?<code> $RE{balanced}{-parens=>'{}'} ) by (?<code> (?&PerlBlock) ) $PPR::GRAMMAR - then the parser will handle a case like print "Hello, World }\n"; too!
Here is one approach: Parse the template file twice. On first parse, write Perl statements from the template to a temp file, for example /tmp/MyTemplate.pm, add some header code to this file such as to make it a valid Perl module. Also use a sequential numbering into package variables for \perlValue statements, i.e. translate the first \perlValue{ list $v } into for example: our $perl_value1 = list $v;, the next \perlValue{ list $w } becomes our $perl_value2 = list $w; and so on..
Then require the module: require "/tmp/MyTmplate.pm"; Then parse the template a second time, extracting the correct values corresponding to Perl code in the template from the symbol table of MyTemplate. For example to get the value of \perlValue{ list $v } use $MyTemplate::perl_value1 and so on..
I'm trying to understand the 'Common Mistake' section in the perldsc documentation. What is the author trying to convey when he mentions:
The two most common mistakes made in constructing something like an array of arrays is either accidentally counting the number of elements or else taking a reference to the same memory location repeatedly. Here's the case where you just get the count instead of a nested array:
for my $i (1..10) {
my #array = somefunc($i);
$AoA[$i] = #array; # WRONG!
}
From what I understand is that when it iterate it will take the first value of (1..10) which is 1 and will pass it to a function like this:
my #array = somefunc(1);
Since that function is not defined, I'll create the logic.
sub somefunc {
my $a = shift;
print $a * $a;
}
which will essentially do this:
1 * 1
and the result is '1'.
To my understanding my #array will look like:
#array = ('1');
And the next line will do:
$AoA[$i] = #array;
I'm assuming that $AoA[$1] is an anonymous array ( he/she didn't declare with 'my', btw) and the #array will be the first element of the this anonymous array which the author said it' WRONG. And the for each loop with iterate to '2'.
somefunc(2);
Which will be '4' and passed to:
$AoA[$i] = #array
What is the point of the author with this code which is wrong. I'm trying to understand what is wrong but more importantly, I'm trying to understand the code. Any help will be appreciated.
UPDATE
I think I understand why this is a common mistake because when I use print and Dumper, I can visually see what the author is trying to convey, here is the revised code.
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
for my $i (1..10) {
my #AoA;
my #array = somefunc($i);
print "The array is Dumper(#array)\n";
$AoA[$i] = #array; # WRONG!
print Dumper($AoA[$i]);
}
sub somefunc {
my $a = shift;
return $a * $a;
}
In the Common Mistakes paragraph of perldoc perldsc, he/she states
Here's the case where you just get the count instead of a nested array:
Below is the output of the Dumper.
The array is Dumper(1)
$VAR1 = 1;
The array is Dumper(4)
$VAR1 = 1;
The array is Dumper(9)
$VAR1 = 1;
The array is Dumper(16)
$VAR1 = 1;
The array is Dumper(25)
$VAR1 = 1;
The array is Dumper(36)
$VAR1 = 1;
The array is Dumper(49)
$VAR1 = 1;
The array is Dumper(64)
$VAR1 = 1;
The array is Dumper(81)
$VAR1 = 1;
The array is Dumper(100)
$VAR1 = 1;
So I'm assuming that the repeated
$VAR1 = 1;
is the count and not the nested array.
The author did indicate that if the count is what I truly want then to rewrite the code like this:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
for my $i (1..10) {
my #count;
my #array = somefunc($i);
print "The array is Dumper(#array)\n";
$count[$i] = scalar #array;
print Dumper($count[$i]);
}
sub somefunc {
my $a = shift;
return $a * $a;
}
But the documentation didn't tell me how to get the nested array?
UPDATE
Correct me if I am wrong but I rewrote the code to get the nested array:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my #count;
my #new_array;
for my $i (1..10) {
#my #count;
my #array = somefunc($i);
push #new_array, [#array];
}
sub somefunc {
my $a = shift;
return $a * $a;
}
print Dumper(\#new_array);
Which printed
$VAR1 = [
[
1
],
[
4
],
[
9
],
[
16
],
[
25
],
[
36
],
[
49
],
[
64
],
[
81
],
[
100
]
];
In the following statement:
$AoA[$i] = #array;
the #array is referenced in a scalar context, yielding a number of its elements. The context is imposed by LHS, that is $AoA[$i] which is a single element of the #AoA array.
In Perl, there are no array of arrays in a strict sense. These are emulated essentially by either "flatten" arrays or array with references. For the latter, you would need to use take reference operator as in:
$AoA[$i] = \#array;
For the starter, you may find, that Data::Dumper is very handy in examining complex data stuctures such as arrayrefs and hashrefs.
Perl is polymorphic, which means that it deals with different data types transparently, and makes what is usually a pretty good guess on how to deal with something. This makes the programmer's work much easier because it is not strongly typed like other languages.
So for example if $i is the number 4, you can do this:
print $i + 1;
and you will see a 5 - pretty logical, right?
and if you do this:
print "I am " , $i , " years old";
You will see "I am 4 years old" - in this case perl says "you are operating in list context, so I will treat $i as a string. No need to convert the number into a string as many other languages insist.
So when you assign
$AoA[$i] = #array;
The way it treats this depends on the context. In scalar context, it will set $AoA[$i] to be the length of the array.
For more information about scalar vs list context, read this answer:
http://perl.plover.com/context.html
Your example isn't very useful in understanding what is going on here as your subroutine always returns "1" - the result of calling print(). If you replace the print() with return() then you will at get different values (1, 4, 9, etc).
But the next line of code:
$AoA[$i] = #array;
Will always assign 1 to the element of #Aoa. That's because You are assigning an array (#array) to a scalar variable ($AoA[$i]) and when you evaluate an array in a scalar context, you get the number of elements in the array.
Now, as your #array only ever has a single element, you could do this:
$AoA[$i] = $array[0];
But that's not really building an array of arrays. What you really want to do is to get a reference to an array.
$AoA[$i] = \#array;
This would be more useful if your subroutine returned more than one value.
sub somefunc {
# Used $x instead of $a as $a has a special meaning in Perl
my $x = shift;
return ($x * $x, $x * $x * $x);
}
for my $i (1..10) {
my #array = somefunc($i);
$AoA[$i] = \#array;
}
As useful tool for exploring this is Data::Dumper. Try adding:
use Data::Dumper;
To the top of your code and:
print Dumper #AoA;
After the foreach loop to see the different data structures that you get back.
I have this 3 lines of code in a sub and I'm trying to write them together on one line only.. but I'm quite lost
my %p = #_;
my $arr = $p{name};
my #a = #$arr;
what's the correct way of doing this?
thank you!
my %p = #_;
#_ is assumed to contain key-value pairs which are then used to construct the hash %p.
my $arr = $p{name};
The argument list is assumed to have contained something along the lines of name, [1, 2, 3,] so that $p{name} is an reference to an array.
my #a = #$arr;
Dereference that array reference to get the array #.
Here is an invocation that might work with this prelude in a sub:
func(this => 'that', name => [1, 2, 3]);
If you want to reduce the whole prelude to a single statement, you can use:
my #a = #{ { #_ }->{name} };
as in:
#!/usr/bin/env perl
use strict;
use warnings;
use YAML::XS;
func(this => 'that', name => [1, 2, 3]);
sub func {
my #a = #{ { #_ }->{name} };
print Dump \#a;
}
Output:
---
- 1
- 2
- 3
If the array pointed to by name is large, and if you do not need a shallow copy, however, it may be better to just stick with references:
my $aref = { #_ }->{ name };
OK so what you're doing is:
Assign a list of elements passed to the sub, to a hash.
extract a value from that hash (that appears to be an array reference)
dereference that into a standalone array.
Now, I'm going to have to make some guesses as to what you're putting in:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
sub test {
my %p = #_;
my $arr = $p{name};
my #a = #$arr;
print Dumper \#a;
}
my %input = ( fish => [ "value", "another value" ],
name => [ "more", "less" ], );
test ( %input );
So with that in mind:
sub test {
print join "\n", #{{#_}->{name}},"\n";
}
But actually, I'd suggest what you probably want to do is pass in the hashref in the first place:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
sub test {
my ( $input_hashref ) = #_;
print Dumper \#{$input_hashref -> {name}};
}
my %input = ( fish => [ "value", "another value" ],
name => [ "more", "less" ], );
test ( \%input );
Also:
Don't use single letter variable names. It's bad style.
that goes double for a and b because $a and $b are for sorting. (And using #a is confusing as a result).
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.
I am relatively new to Perl and I do not want to use the List::Util max function to find the maximum value of a given array.
When I test the code below, it just returns the first value of the array, not the maximum.
sub max
{
my #array = shift;
my $cur = $array[0];
foreach $i (#array)
{
if($i > $cur)
{
$cur = $i;
}
else
{
$cur = $cur;
}
}
return $cur;
}
Replace
my #array = shift;
with
my #array = #_;
#_ is the array containing all function arguments. shift only grabs the first function argument and removes it from #_. Change that code and it should work correctly!
Why don't you want to use something that works?
One of the ways to solve problems like this is to debug your data structures. At each step you print the data you have to see if what you expect is actually in there. That can be as simple as:
print "array is [#array]\n";
Or for complex data structures:
use Data::Dumper;
print Dumper( \#array );
In this case, you would have seen that #array has only one element, so there it must be the maximum.
If you want to see how list assignment and subroutine arguments work, check out Learning Perl.
You can write the function as:
#!/usr/bin/perl
use strict; use warnings;
print max(#ARGV);
sub max {
my $max = shift;
$max >= $_ or $max = $_ for #_;
return $max;
}
However, it would be far more efficient to pass it a reference to the array and even more efficient to use List::Util::max.