Why is my for loop an illegal declaration - perl

I created two subs one to do Fibonacci and the other to test even numbers. When I call it though it is saying my for loop in line 7 the sub Fibonacci is illegal why?
#!/usr/bin/perl
use strict;
use warnings;
my ($x,$y);
my $num = 0;
sub Fibs($start,$stop){
for ($start..$stop){
($x, $y) = ($y, $x+$y);
my $total += $y;
}
print "$total \n"
}
sub even($num){
if ($num % 2 == 0){
return $num;}
}
my $big_total = Fibs(even($num), 3999999)
Edited from suggestions below.
Clearly I am missing something. From feedback updated to new version.
#!/usr/bin/perl
use strict;
use warnings;
my ($x,$y);
my $num = 0;
sub Fibs{
my ($start, $stop) = #_ ;
for ($start..$stop){
my ($x, $y) = (0,2);
if ($x % 2 == 0){
($x, $y) = ($y, $x+$y);
my $total += $y;
}
}
my $big_total = Fibs(0, 3999999)

In addition to the missing opening braces, Perl doesn't support that kind of declaration for subroutine parameters.
Rather than
sub Fibs($start, $stop) {
...
}
you need to write something like:
sub Fibs {
my($start, $stop) = #_;
...
}
(Perl does have prototypes, but they're not really intended for declaring the types of parameters, and they don't provide names. See this article for a discussion.)
Other problems:
You should add
use strict;
use warnings;
You never use the $x and $y that you declare in the outer scope.
Your even function appears to be incomplete. It doesn't (explicitly) return a value if its argument is an odd number. What exactly is it intended to do?

Related

Use bigint and float perl

I am extremely new to Perl, so I hope you will excuse my inexperience.
I have the following lines of code:
use warnings;
use strict;
use POSIX 'ceil';
use bigint;
my($g, $y, $n) = ($ARGV[0], $ARGV[1], $ARGV[2]);
my $z = ceil(sqrt($n-1));
my $entry;
print "list1: \n";
for my $v (0 .. $z) {
$entry = ($g ** $v) % $n;
$entry = ($entry ** ($n - 2)) % $n;
$entry = ($entry * $y) % $n;
print "$entry : $v\n";
}
print "list2: \n";
for my $u (0 .. $z) {
$entry = ($g ** ($u * $z)) % $n;
print "$entry: $u\n";
}
I need to use the bigint environment because of some following statements. Whenever I look into $z it evaluates to 6 instead of 7, when i call my program with $n = 41. It looks as if the bigint environment rounds the value of the sqrt method. I also tried to use BigFloat instead of bigint, but then the result of $entry = ($g ** ($u * $z)) % $n; gets calculated wrong (with ($g, $y, $n) = (15, 38, 41) the result is 3, when $u reached 3 in the for loop, but should be 26 instead).
Is there any option to avoid this rounding, so I can use float while calculating the square root and bigint in all following statements, so the pow operation works properly?
My call is perl program.pl 15 38 41. I try to implement the baby-step-giant-step algorithm.
you need to use bignum, not bigint:
$ cat bauer.pl
#!/usr/bin/perl
use warnings;
use strict;
use POSIX;
use bigint;
my($g, $y, $n) = ($ARGV[0], $ARGV[1], $ARGV[2]);
my $z = ceil(sqrt($n-1));
$ perl r.pl
1.41421356237309504880168872420969807857
With your program signature:
$ cat bauer.pl
#!/usr/bin/perl
use warnings;
use strict;
use POSIX;
use bignum;
my($g, $y, $n) = ($ARGV[0], $ARGV[1], $ARGV[2]);
my $z = ceil(sqrt($n-1));
print STDOUT "$z\n";
$ perl bauer.pl 1 2 48
7
I'd recommend Math::BigFloat and Math::BigInt over the bigint pragma, practically always.
The pragma is "just a thin wrapper around various modules of the Math::BigInt family" says the (linked) doc, but has very non-trivial actions (the "Description" conveys it). Instead, use the classes to set up what you want burdened with infinite precision support, itself non-trivial and costly.
use warnings;
use strict;
use feature 'say';
use Math::BigFloat;
my($g, $y, $n) = ($ARGV[0], $ARGV[1], $ARGV[2]);
my $z = sqrt($n-1);
say $z;
my $num = Math::BigFloat->new( $z );
say $num;
my $num_ceil = $num->bceil();
say $num_ceil;
Update The shown calculation has no need for a big-number exponent
use warnings;
use strict;
use feature 'say';
use POSIX 'ceil';
use Math::BigInt;
my ($g, $y, $n) = #ARGV;
my $z = ceil(sqrt($n-1));
my $bg = Math::BigInt->new($g);
my $e;
for my $u (0 .. $z) {
$e = $bg->copy->bmodpow($u*$rnd, $n);
say "$u: $e";
}
There happens to be a bmodpow method, doing exactly what's needed and being
"far superior" at it. Most arithmetic methods modify their operands, thus copy() is chained in to preserve $bg for the next iteration. See "Modifying and =" bullet under Caveats in docs.
I declare $e outside of the loop to avoid the (copy) constructor running every time in the loop as the variable becomes (is assigned) a BigInt object, returned by the method. (I am not certain that this is needed or that it helps though.)
Whenever I look into $z it evaluates to 6 instead of 7,
use bigint; causes numeric literals to be replaced with Math::BigInt objects. For example,
1
gets replaced with
Math::BigInt->new(1)
Math::BigInt in turn overrides a number of operators when a Math::BigInt object is used as an operand.
As such,
use bigint;
my $z = ceil(sqrt($n-1));
is equivalent to
use Math::BigInt;
my $z = ceil(sqrt($n-Math::BigInt->new(1)));
which is equivalent to
use Math::BigInt;
my $temp = Math::BigInt->new(1); # 1 [BigInt]
$temp->bneg; # -1 [BigInt]
$temp->badd($n); # 40 [BigInt]
$temp->bsqrt(); # 6 [BigInt] <--- XXX
$temp = $temp->numify; # 6 [Primitive]
my $z = ceil($temp); # 6 [Primitive]
So, you are using a Math::BigInt when you don't want to. Don't do that!!! Simply use
# No "use bigint;"!!!
my $z = ceil(sqrt($n-1));
Of course, the algorithm to which you linked actually calls for
# No "use bigint;"!!!
my $z = ceil(sqrt($n));
Because use bigint; can have large effects at a distance, I personally find use bigint; far too magical. I'd much rather use Math::BigInt->new(...) where appropriate rather than having use bigint; convert all my numerical constants into Math::BigInt objects. I'd also rather use Math::BigInt's methods instead of overloaded operators. Far less surprises that way (e.g. such as the loss of big number support when using ceil).
use warnings;
use strict;
use feature qw( say );
use Config qw( %Config );
use Math::BigInt qw( );
use POSIX qw( ceil );
# Each of the arguments is expected to be in [0, 2^32).
# Should use exponentiation by squaring instead of larger number support.
sub pow_m {
my ($base, $exp, $mod) = #_;
my $n = Math::BigInt->new($base);
$n->bpow($exp);
$n->bmod($mod);
return $n->numify();
}
# Each of the arguments is expected to be in [0, 2^32).
# Requires a 64-bit integers or $e might overflow.
sub babystep_giantstep {
my ($g, $h, $mod) = #_;
my $m = ceil(sqrt($mod));
my %table;
my $e = 1;
for my $i (0..$m-1) {
$table{$e} = $i;
$e = ($e * $g) % $mod;
}
my $factor = pow_m($g, $mod-$m-1, $mod);
$e = $h;
for my $i (0..$m-1) {
if (exists($table{$e})) {
return $i*$m + $table{$e};
}
$e = ($e * $factor) % $mod;
}
return undef;
}
{
$Config{uvsize} >= 8
or warn("Results may overflow\n");
my ($g, $h, $mod) = #ARGV;
my $log = babystep_giantstep($g, $h, $mod);
say $log;
my $test = Math::BigInt->new($g);
$test->bpow($log);
$test->bmod($mod);
$test = $test->numify;
say $test == $h ? "ok" : "not ok";
}

Modify variable in Perl subroutine

How do I pass a local variable to a Perl subroutine and modify it?
use strict;
use warnings;
sub modify_a
{
# ????
}
{
my $a = 5;
modify_a($a);
print "$a\n"; # want this to print 10
}
sub modify_a {
$_[0] *= 2;
}
The elements of #_ are aliases to the values passed in, so if you modify that directly, you'll change the caller's values. This can be useful sometimes, but is generally discouraged as it is usually a surprise to the caller.
A less magical approach is to pass a reference.
use strict;
use warnings;
sub modify_a
{
my ($a_ref) = #_;
$$a_ref = 10;
}
{
my $a = 5;
modify_a(\$a);
print "$a\n";
}

Recursive Subroutine Reference

I have tested the following code with perl 5.8 (codepad) and perl 5.16 . There's probably some deeper principle I'm missing and I'm curious what the logic behind this behavior is. Thanks.
The following simple recursive subroutine reference
use strict;
use warnings;
my $fact = sub {
my $n = shift;
if ($n == 0) {
return 1;
}
return $n * $fact->($n-1);
};
print $fact->(100);
results in the error
Global symbol "$fact" requires explicit package name at line 9.
Execution aborted due to compilation errors.
declaring variable before defining it does not produce this error.
use strict;
use warnings;
my $fact;
$fact = sub {
my $n = shift;
if ($n == 0) {
return 1;
}
return $n * $fact->($n-1);
};
print $fact->(100);
my returns the new lexical, so it can be used to assign to it in the same statement in which it was declared. However, any further references to that name only resolve to that lexical beginning with the next statement.
So separate the declaration:
my $fact;
$fact = sub { ... $fact ... }
This rule is in fact sometimes useful; you can have an outer lexical and an inner one and assign between the two:
my $foo = 42;
{
my $foo = $foo;
$foo += 42;
print "foo is $foo\n";
}
print "foo is $foo\n";
If you have a recent version of Perl, you don't actually need to access $fact within the subroutine because the __SUB__ pseudo-constant offers a reference to the current subroutine.
use 5.016;
my $fact = sub {
my $n = shift;
if ($n == 0) {
return 1;
}
return $n * __SUB__->($n-1);
};
Note that in the first example (where the $fact variable is used within the sub), a reference cycle is created, which might lead to Perl leaking memory over time. __SUB__ is a fairly clean way to resolve that issue. (Other solutions to the problem include the Y-combinator and reference weakening.)

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];
}

Routine as argument -- generic variables not working

I am working on writing a gaming system (wargames, etc.) and am creating the system for creating and displaying hex maps. I realized quickly that I am repeatedly doing a nested loop of x=(0..maxx) and y=(0..maxy). So I attempted to adapt some code I found somewhere (one of the advanced perl books, I forget where) to create an easier way to do this sort of looping thing. This is what I came up with:
sub fillmap (&#) {
my $code = shift;
no strict 'refs';
use vars qw($x $y);
my $caller = caller;
local(*{$caller."::x"}) = \my $x;
local(*{$caller."::y"}) = \my $y;
foreach $x (0..5) {
foreach $y (0..3) {
warn "fillmap $x,$y\n";
&{$code}($x,$y);
}
}
}
It's suppose to work like sort, but using $x and $y instead of $a and $b.
Note: the warn statement is for debugging. I also simplified the x and y ranges (the array passed in determines the maxx and maxy values, but I didn't want to muddy this discussion with the routines for calculating them... I just hard-coded them to maxx=5 and maxy=3)
So, this execution of this routine like so:
fillmap {warn "$x,$y\n";} #map;
should yield a list of the x,y pairs. But instead, it gives me this:
fillmap 0,0
,
fillmap 0,1
,
fillmap 0,2
,
fillmap 0,3
,
fillmap 1,0
,
...
Note, the "fillmap" lines are from the subroutine for debugging. But instead of each x,y pair, I just get the comma ($x and $y are undefined).
What am I doing wrong?
The problem is that for $x does its own localisation. The $x inside the loop isn't the $x that's aliased to $caller::x.
You need to do one of the following:
Copy $x into $caller::x inside the loop.
Alias $caller::x to $x inside the loop.
The following does the latter:
use strict;
use warnings;
sub fillmap(&#) {
my $code = shift;
my $caller = caller();
my $xp = do { no strict 'refs'; \*{$caller.'::x'} }; local *$xp;
my $yp = do { no strict 'refs'; \*{$caller.'::y'} }; local *$yp;
for my $x (0..1) {
*$xp = \$x;
for my $y (0..2) {
*$yp = \$y;
$code->();
}
}
}
our ($x, $y);
fillmap { warn "$x,$y\n"; } '...';
You could avoid the need for our ($x, $y); by using $a and $b instead of $x and $y. You can't solve the problem by moving it (or use vars qw( $x $y );) into fillmap because you obviously intend fillmap to be used in a different package and lexical scope than the caller.