user786 has asked for the wisdom of the Perl Monks concerning the following question:

I have written a function in perl (Thanks to perl monk) The below script works as expected and provides the desired output. I have been learning about functions and making function calls. I'm trying to make a function call by assigning it to a variable.

use strict; use Carp; use warnings; use autodie; use feature qw/say/; use Net::SSH::Expect; print "\n[INFO] script Execution Started\n"; #-- ssh into a router my $ssh = Net::SSH::Expect->new( host => "ip addr", password => 'password', user => 'user name', raw_pty => 1, ); my $login_output = $ssh->login(); #--Function to read config file and execute the commands on the rout +er accordingly. sub mysub { my ($ssh,$filename) = @_; $ssh->exec("cmd 1"); $ssh->exec("cmd 2"); open my $p, '<', $filename; while (my $config = <$p>) { chomp $config; my $conf = $ssh->exec("$config"); print("$conf"); } } #--> Function call. mysub($ssh,"file name.txt");
Now I tried making the function call my assigning it to a variable $p and that should throw an error if some thing goes wrong in the function. This is what i tried .
my $p = mysub($ssh," file name.txt "); if ($p) { print {*STDERR} "Something went wrong [$p]." or carp 'Could not print error about the config file'; return 0; }

However this is not working. Any suggestions ?

Replies are listed 'Best First'.
Re: Perl function calls.
by toolic (Bishop) on Jul 07, 2014 at 14:50 UTC
    From perlsub:
    If no return is found and if the last statement is an expression, its value is returned. If the last statement is a loop control structure like a foreach or a while , the returned value is unspecified.

    Since you have a while loop as the last statement, the returned value is undefined.

    UPDATE: Perl : Convert a monolithic code to a function

Re: Perl function calls.
by hardburn (Abbot) on Jul 07, 2014 at 14:53 UTC

    What did you do to test it? Were you expecting a failure? Are you sure that this test method actually produces a failure?

    Of note, the call to open in the sub won't throw an error on its own. You need to check its return value:

    open my $p, '<', $filename or return "Could not open $filename: $!";

    Which should be compatible with the way you intended to catch errors. However, I'll also point out that or die "error message" tends to be the preferred way of doing this rather than or return "error message".


    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

      This method actually did not produce any failure. Yes that correct,die is preferred way. I have used auto die in the script. But I'd like to know/learn how it works with the return message.

      It would be really helpful for me if you can help me understand it.

        Well, if it didn't return failure, then I'm not sure how you can say your error code didn't work. If there's no failure for it to catch, then of course it won't run.

        As it is, your error code should work fine if the function is expected to return an error string on failure. Since the function doesn't return an error string in any branch, the error will never be picked up.


        "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: Perl function calls.
by BillKSmith (Monsignor) on Jul 07, 2014 at 15:53 UTC
    It is not clear from your text what you intend to assign to the variable $p. It could be either a reference to the function or the return value from the function. Your code correctly implements the latter. The other responders assume that is what you intend. Is it?
    Bill
      i'm trying to call the function from $p and assign the return value to it
        But you're not returning anything from the function. Which means it will return the value of the last thing evaluated. And that is 'while' loop in your function (it counts as a whole thing). So what does it return? Let's use the standard library module Devel::Peek to peek inside Perl's internals...
        use Devel::Peek; # exports 'Dump' function sub fn { my $i = 5; while ($i < 10) { $i += 1; } } my $p = fn(); Dump $p;
        And here's the output:
        SV = PVNV(0x1007070) at 0x102ac18 REFCNT = 1 FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK) IV = 0 NV = 0 PV = 0x1016880 ""\0 CUR = 0 LEN = 10
        Pretty interesting! Apparently, the 'while' loop returns empty string (actually, number 0 and empty string at once). That is, it returns false. Let's try with some string now...
        use Devel::Peek; sub fn { my $i = 5; while ($i < 10) { $i += 1; } 'some string'; } my $p = fn(); Dump $p;
        SV = PV(0x1f25e20) at 0x1f47c28 REFCNT = 1 FLAGS = (PADMY,POK,IsCOW,pPOK) PV = 0x1fa22f0 "some string"\0 CUR = 11 LEN = 13 COW_REFCNT = 1
        Now it returns 'some string' (look at PV value).

        So, basically, just use 'return' keyword if you want to return something from your function. Loops don't return anything particularly useful.

Re: Perl function calls.
by perlfan (Parson) on Jul 07, 2014 at 15:47 UTC
    mysub isn't returning anything meaningful (i.e., whatever the result of the final print statement is.) What do you wish to get from it?

    And why are you returning from inside of an if statement?