FAQ
Hi there List people,

I am hoping to send a hash and a scalar to a subroutine but the variable
is not completely being sent. Below is the error message below is
showing something is not getting passed that well to the subroutine.
Looks like %login is empty.


--- snip ---

$ret{$hostnames[0]} = $login{$hostnames[0]}->send_cmd("edit");
$ret{$hostnames[1]} = $login{$hostnames[1]}->send_cmd("edit");

if ($ret{$hostnames[0]} =~ /^blah/m) {
exiting ($hostnames[0], %login);
}

if ($ret{$hostnames[1]} =~ /^blah/m) {
exiting ($hostnames[1], %login);
}


sub exiting {
my ($hostname, %login) = @_;
my ($ret);
print "login: $login $hostname\n";
my ( $position, $error, $matched, $before, $after ) =
$login{$hostname} -> send("exit\n");
print "position: $position, $error, $matched, $before, $after \n";
exit 0;
if ($ret{$hostname} =~ /^blah/m) {
$login{$hostname}->send_cmd("yes")
}
$ret{$hostname} = $login{$hostname}->send_cmd("exit");
}



---- snip ----

here is the beginning of send_cmd called from a perl module library.

---- snip ----

sub send_cmd {
my ( $self, $seconds, $cmd ) = @_;
if ( !$cmd ) {
if ( $seconds !~ /^\d+/ ) {
$cmd = $seconds;
$seconds = 10;
}
} ## end if ( !$cmd )
chomp $cmd;

--- snip ----


here is the error message below is showing something is not
getting passed that well to the subroutine. Looks like %login is empty.



----- snip ----


Use of uninitialized value in concatenation (.) or string

--- snip ----


Cheers,
Noah

Search Discussions

  • Jim Gibson at Dec 9, 2009 at 1:56 am
    On 12/8/09 Tue Dec 8, 2009 5:41 PM, "Noah" <noah-list@enabled.com>
    scribbled:
    Hi there List people,

    I am hoping to send a hash and a scalar to a subroutine but the variable
    is not completely being sent. Below is the error message below is
    showing something is not getting passed that well to the subroutine.
    Looks like %login is empty.
    If %login were "empty", then the line $login{$hostname}->send("exit"); would
    result in a different error: Can't call method "send" on an undefined value.

    It is more likely that one or all of $position, $error, $matched, $before,
    or $after are assigned an undefined value by the call to
    $login{$hostname}->send("exit"), perhaps because of an error. Does that
    method have any error checking or error return value?
    $ret{$hostnames[0]} = $login{$hostnames[0]}->send_cmd("edit");
    $ret{$hostnames[1]} = $login{$hostnames[1]}->send_cmd("edit");

    if ($ret{$hostnames[0]} =~ /^blah/m) {
    exiting ($hostnames[0], %login);
    }

    if ($ret{$hostnames[1]} =~ /^blah/m) {
    exiting ($hostnames[1], %login);
    }


    sub exiting {
    my ($hostname, %login) = @_;
    my ($ret);
    print "login: $login $hostname\n";
    my ( $position, $error, $matched, $before, $after ) =
    $login{$hostname} -> send("exit\n");
    print "position: $position, $error, $matched, $before, $after \n";
    exit 0;
    You do realize that the following lines will not be executed, don't you?
    if ($ret{$hostname} =~ /^blah/m) {
    $login{$hostname}->send_cmd("yes")
    }
    $ret{$hostname} = $login{$hostname}->send_cmd("exit");
    }
    Use the Data::Dumper module to inspect the contents of %login:

    use Data::Dumper;
    ...

    print Dumper(\%login);
  • Jeff Pang at Dec 9, 2009 at 1:59 am

    Noah:


    sub exiting {
    my ($hostname, %login) = @_;
    Passing arguments like this has no such problem.
    But you'd better pass the hash as a reference to the subroutine.

    exitint($hostname, \%login);

    sub exiting {
    my $hostname = shift;
    my %login = %{+shift};
    ...
    }

    print "login: $login $hostname\n";
    I don't see where you defined the variable of $login.
    Have you 'use strict' and 'use warnings'?
  • Steve Bertrand at Dec 9, 2009 at 2:06 am

    Jeff Pang wrote:
    Noah:
    sub exiting {
    my ($hostname, %login) = @_;
    Passing arguments like this has no such problem.
    But you'd better pass the hash as a reference to the subroutine.
    ...or bundle _all_ parameters into a hashref, which I've found to be
    ohhhhh so extensible, with no risk of accidentally using the hash as
    part of an array :)
    exiting($hostname, \%login);
    exiting({
    hostname => $hostname,
    login => \%login,
    });
    sub exiting {
    my $hostname = shift;
    my %login = %{+shift};
    ...
    }
    sub exiting {
    my $params = shift;
    my $hostname = $params->{ hostname };
    my $login = $params->{ login };

    use Data::Dumper;
    print Dumper $params;
    #...
    }
  • John W. Krahn at Dec 9, 2009 at 2:10 am

    Jeff Pang wrote:
    Noah:
    sub exiting {
    my ($hostname, %login) = @_;
    Passing arguments like this has no such problem.
    But you'd better pass the hash as a reference to the subroutine.

    exitint($hostname, \%login);

    sub exiting {
    my $hostname = shift;
    my %login = %{+shift};
    What is the point of passing a reference if you are just going to copy
    the whole hash anyway (which is what the OP was doing)?




    John
    --
    The programmer is fighting against the two most
    destructive forces in the universe: entropy and
    human stupidity. -- Damian Conway
  • Jeff Pang at Dec 9, 2009 at 3:04 am

    John W. Krahn:
    Jeff Pang wrote:
    Noah:
    sub exiting {
    my ($hostname, %login) = @_;
    Passing arguments like this has no such problem.
    But you'd better pass the hash as a reference to the subroutine.

    exitint($hostname, \%login);

    sub exiting {
    my $hostname = shift;
    my %login = %{+shift};
    What is the point of passing a reference if you are just going to copy
    the whole hash anyway (which is what the OP was doing)?
    If people want to change the hash's elements in subroutine and don't
    want to influence the original one, then passing a copy is right.
    Otherwise copy a hash is wasteful for memory, given the size is large. :)
  • Philip Potter at Dec 9, 2009 at 8:00 am

    2009/12/9 John W. Krahn <jwkrahn@shaw.ca>:
    Jeff Pang wrote:
    Noah:
    sub exiting {
    my ($hostname, %login) = @_;
    Passing arguments like this has no such problem.
    But you'd better pass the hash as a reference to the subroutine.

    exitint($hostname, \%login);

    sub exiting {
    my $hostname = shift;
    my %login = %{+shift};
    What is the point of passing a reference if you are just going to copy the
    whole hash anyway (which is what the OP was doing)?
    One possible reason is that if you later want to add a new, optional
    parameter to the subroutine, you can do this without modifying the
    existing interface (and therefore modifying all code which calls
    exiting):

    sub exiting {
    my $hostname = shift;
    my %login = %{+shift};
    my $optional = shift // $default_value; # use || before 5.10 and be careful
    # ...
    }

    This isn't possible if you are passing the hash as a list:

    sub exiting {
    my ($hostname, %login) = @_;
    my $optional = ??? # whoops, we've used all arguments already
    }

    I'd therefore argue that passing a hashref is more maintainable.

    Phil

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedDec 9, '09 at 1:42a
activeDec 9, '09 at 8:00a
posts7
users6
websiteperl.org

People

Translate

site design / logo © 2022 Grokbase