Calling another function through eval by passing arguments in Perl - perl

I have written the following code for passing arguments to eval function in sample.pl and calling the function in another Perl file sample1.pl.
sample1.pl:
use strict;
use warnings;
require 'sample.pl';
use subs "hello";
my $main2 = hello();
sub hello
{
print "Hello World!\n";
our $a=10;
our $b=20;
my $str="sample.pl";
my $xc=eval "sub{$str($a,$b)}";
}
Sample.pl
use strict;
use warnings;
our $a;
our $b;
use subs "hello_world";
my $sdf=hello_world();
sub hello_world($a,$b)
{
print "Hello World!\n";
our $c=$a+$b;
print "This is the called function from sample !\n";
print "C: " .$c;
} 1;
I am getting output as:
Illegal character in prototype for main::hello_world : $a,$b at D:/workspace/SamplePerl_project/sample.pl line 6.
Use of uninitialized value $b in addition (+) at D:/workspace/SamplePerl_project/sample.pl line 9.
Use of uninitialized value $a in addition (+) at D:/workspace/SamplePerl_project/sample.pl line 9.
Hello World!
This is the called function from sample !
C: 0Hello World!
can u guys show me a solution for this how to call a function through eval by passing arguments

how to call a function through eval by passing arguments?
sub func {
print join(", ", #_), "\n";
return 99;
}
my ($str, $a, $b) = ('func', 10, 'tester');
my $f = eval "\\&$str" or die $#;
my $c = $f->($a, $b);
print "c = $c\n";
But there's need to use eval. The above can be written as
my $f = \&$str;
my $c = $f->($a, $b);
or even
my $c = (\&$str)->($a, $b);

Try this This will help u..
my $action="your function name";
if ($action) {
eval "&$action($a,$b)";
}
in Receiving function
sub your function name {
my ($a,$b) =#_;#these are the arguments
}

Related

How to print only caller function in Perl

I am trying to print caller function in Perl. Its displaying as per the expectation.
Below is the code:
#!/usr/bin/perl
use strict; use warnings;
my $a = 5;
my $b = fun1($a);
print "a:$a ** b:$b\n";
sub fun1 {
my $r = shift;
my $s = fun2($r);
return $s;
}
sub fun2 {
my $p = shift;
print "the calling function is:", (caller 1)[3], "\n";
print "and you're in:", (caller 0)[3], "\n";
my $q = $p * 5;
return $q;
}
Output:
the calling function is:main::fun1
and you're in:main::fun2
a:5 ** b:25
How can I print only fun1 and fun2 instead of main::fun1 and main::fun2 respectively.
If there is a way to print them according to I stated above its good. Or I would have to trim the result :(
You can use the following:
my $name = $full_name =~ s/^.*:://sr;

how can I display a variable's name in perl, along with the value of the variable?

To diagnose or debug my perl code, I would like to easily display the name of a variable along with its value. In bash, one types the following:
#!/bin/bash
dog=pitbull
declare -p dog
In perl, consider the following script, junk.pl:
#!/usr/bin/perl
use strict; use warnings;
my $dog="pitbull";
my $diagnosticstring;
print STDERR "dog=$dog\n";
sub checkvariable {
foreach $diagnosticstring (#_) { print "nameofdiagnosticstring=$diagnosticstring\n"; }
}
checkvariable "$dog";
If we call this script, we obtain
bash> junk.pl
dog=pitbull
nameofdiagnosticstring=pitbull
bash>
But instead, when the subroutine checkvariable is called, I would like the following to be printed:
dog=pitbull
This would make coding easier and less error-prone, since one would not have to type the variable's name twice.
You can do something like this with PadWalker (which you'll need to install from CPAN). But it's almost certainly far more complex than you'd like it to be.
#!/usr/bin/perl
use strict;
use warnings;
use PadWalker 'peek_my';
my $dog="pitbull";
print STDERR "dog=$dog\n";
sub checkvariable {
my $h = peek_my(0);
foreach (#_) {
print '$', $_,'=', ${$h->{'$'. $_}}, "\n";
}
}
checkvariable "dog";
Data::Dumper::Names may be what you're looking for.
#! perl
use strict;
use warnings;
use Data::Dumper::Names;
my $dog = 'pitbull';
my $cat = 'lynx';
my #mice = qw(jumping brown field);
checkvariable($dog, $cat, \#mice);
sub checkvariable {
print Dumper #_;
}
1;
Output:
perl test.pl
$dog = 'pitbull';
$cat = 'lynx';
#mice = (
'jumping',
'brown',
'field'
);
(not an answer, a formatted comment)
The checkvariable sub receives only a value, and there's no (simple or reliable) way to find out what variable holds that value.
This is why Data::Dumper forces you to specify the varnames as strings:
perl -MData::Dumper -E '
my $x = 42;
my $y = "x";
say Data::Dumper->Dump([$x, $y]);
say Data::Dumper->Dump([$x, $y], [qw/x y/])
'
$VAR1 = 42;
$VAR2 = 'x';
$x = 42;
$y = 'x';
Something as following usually helps
use strict;
use warnings;
use Data::Dumper;
my $debug = 1;
my $container = 20;
my %hash = ( 'a' => 7, 'b' => 2, 'c' => 0 );
my #array = [ 1, 7, 9, 8, 21, 16, 37, 42];
debug('container',$container) if $debug;
debug('%hash', \%hash) if $debug;
debug('#array', #array) if $debug;
sub debug {
my $name = shift;
my $value = shift;
print "DEBUG: $name [ARRAY]\n", Dumper($value) if ref $value eq 'ARRAY';
print "DEBUG: $name [HASH]\n", Dumper($value) if ref $value eq 'HASH';
print "DEBUG: $name = $value\n" if ref $value eq '';
}
But why not run perl script under build-in debugger? Option -d
The Perl Debugger

Perl Sub routine to get the square of a number

I am trying to write a subroutine to demonstrate getting a subroutine of a number as a function in Perl. I have no idea how to use the #_ operator in perl
#!/usr/bin/perl
use strict ;
use warnings ;
my $number = $ARGV[0] ;
if (not defined $number) {
die " I need a number to multiply" }
sub square {
my $number = shift ;
print "$number\n"
return $number * $number ;
}
my $result = square() ;
print "$result";
Your subroutine expects a number as first argument. You access the argument when you do :
my $number = shift;
Which is actually roughly equivalent to :
my ($number) = #_;
So as you can see, #_ is a special variable that represents the list of arguments that were passed to the subroutine.
The problem in your code is that you do not pass any argument to your sub. This :
my $result = square();
Should be written as :
my $result = square($number);
You are not passing $number to your sub. Try this:
#!/usr/bin/perl
use strict ;
use warnings ;
my $number = $ARGV[0] ;
die "I need a number to multiply" unless(defined $number);
sub square {
my $number = shift ;
print "$number\n";
return $number * $number;
}
my $result = square($number);
print "$result\n";

Non-defined return of sub

How can I avoid that a variable gets touched by a return of a subfunction. I wrote following code snippet
#!/usr/bin/perl
use strict;
use warnings;
my $a = "init";
sub funct{
my $var;
#$var = 1;
return $var if defined $var;
}
my $tmp = funct;
$a = $tmp if defined $tmp;
print "$a\n";
and I don't want the value of $a be changed from it's initial init if $var isn't defined in the subfunction.
Where is the error or is there a better way to solve this problem?
Greetings
The return $foo if $bar is equivalent to $bar and return $foo. Therefore, when $bar is false, then this statement evaluates to the value of $bar. As subroutines return the value of the last executed statement, your sub returns either $var if it is defined, or a false value, if not.
You can either go the explicit route, and put another return there:
# all branches covered
return $var if defined $var;
return;
This is silly, and equivalent to return $var.
Now the false value that your sub returns is in fact defined, so it is assigned to $a. You could test for truth instead:
$a = $tmp if $tmp;
… but that opens another can of worms.
Return values are extraordinary bad at telling us whether they are the wanted return value, or an error indicator. There are two clean ways around that:
Return a second value that tells us whether the function exited OK:
sub func {
my $var;
return (1, $var) if defined $var;
return (0); # not strictly needed
}
my ($ok, $tmp) = func();
$a = $tmp if $ok;
(basically, the comma-ok idiom as seen in Golang)
Return a container that has to be destructured to obtain the actual return value. A possibility is to either return undef (or something false) on error, or a scalar reference to the value when such a value exists:
sub func {
my $var;
return \$var if defined $var;
return undef; # actually not needed
}
my $tmp = func();
$a = $$tmp if defined $tmp;
(basically, a Maybe type as seen in Haskell)
Here is a way to use that without obious temp vars:
($a) = map { $_ ? $$_ : () } func(), \$a;
You can avoid temporary variable,
$a = funct() // $a;
Running this program in the Perl debugger shows that $tmp is set to an empty string, which evaluates to true with the defined function. This is why the conditional that sets $a evaluates to true:
$ perl -d
Loading DB routines from perl5db.pl version 1.33
Editor support available.
Enter h or `h h' for help, or `perldoc perldebug' for more help.
use strict;
use warnings;
my $a = "init";
sub funct{
my $var;
#$var = 1;
return $var if defined $var;
}
my $tmp = funct;
$a = $tmp if defined $tmp;
print "$a\n";
__END__
main::(-:4): my $a = "init";
DB<1> x $a
0 undef
DB<2> n
main::(-:12): my $tmp = funct;
DB<2> x $a
0 'init'
DB<3> x $tmp
0 undef
DB<4> n
main::(-:14): $a = $tmp if defined $tmp;
DB<4> x $tmp
0 ''
To fix, simply return $var, without the if defined $var. This will set $tmp to undef
It looks like you're trying to detect error scenarios by returning undef. In addition to #amon's suggestions, you could die out of funct when an error occurs:
#!/usr/bin/perl
use strict;
use warnings;
my $a = "init";
sub funct{
my $var;
...
if ($something_went_wrong) {
die 'something bad';
}
...
return $var;
}
eval {
$a = funct;
1;
} or do {
# log/handle the error in $#
};
print "$a\n";

Breakpoint in function in different file

I have two Perl files like this. Using perl5db.pl I am trying to set a breakpoint at line 7 in file2.pl but sadly it doesn't let me. I looked for answers, and found that I can use modules, but file2.pl isn't using modules. What can I do?
#file.pl is
#!/usr/bin/perl
use strict;
use warnings;
require "file2.pl";
# This file is a test file to run the debugger on.
hello();
my $var = 1;
my $var2 = 2;
makeEqual();
sub main {
if($var == $var2){
print "they are equal\n";
}
else {
print "they are not equal\n";
makeEqual();
}
my $value =2;
print "the value is $value\n";
}
sub makeEqual {
$var = $var2;
my $str = " this is crazy";
$str =~ s/\s+/ /g;
print "$str is done \n";
}
main();
#file2.pl is
#!/usr/bin/perl
use strict;
use warnings;
sub hello {
print "I am in hello";
}
1;
Just after init your debugger set a breakpoint to stop after compiling your function of file2.pl, and when the debugger stops at that point, the return statement (instruction 1;) you will be able to see the hello function of that file.
Execute the debugger:
perl -d file.pl
Stop when function hello is compiled:
DB<1> b compile hello
Continue:
DB<2> c
Now function hello exists so set a breakpoint in it and continue:
DB<2> b hello
DB<3> c
Now you are there:
main::hello(file2.pl:7): print "I am in hello";