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

Hi Monks

I'm new to references and having a tough time understanding how to use them, even after checking out perlreftut. I'm trying to pass an array to a subroutine makeSql and then iterate over each of the members of the array. For now I'm just printing out the members as a string while I figure out how to get this to work. Later this subroutine will use each of the items in this array as part of a SQL select statement.

#!/usr/bin/perl -w use strict; my @xpid = ("ahuman","alienh","pmonk"); my $sql = makeSql(\@xpid); warn "$sql\n"; sub makeSql { my @xpid = shift; my $return; my $i = 0; foreach my $item (@xpid) { $return .= $xpid[$i]; $i++; } return $return; }

As you probably already know, this warns something like ARRAY(0x8100a38). Can anyone show me how to use references properly to pass an array to a subroutine and iterate through that array? I've figured out that w my current code I can delete the for loop, assign the global \@xpid to a scalar and do something like $return = $xpid[0] and get a value... but how do I work w/ an array w/out using the global?

AH

----------
Using perl 5.6.1 unless otherwise noted. Apache 1.3.27 unless otherwise noted. Redhat 7.1 unless otherwise noted.

Replies are listed 'Best First'.
Re: Help w passing array by ref
by Abigail-II (Bishop) on Oct 10, 2003 at 16:20 UTC
    You are passing in a reference to an array in the function. References are scalars. The line
    my @xpid = shift;
    is very misleading. All it does is create a one element array @xpid, whose only element is a reference to the original array. It's better to write the first line as:
    my $xpid_ref = shift;

    Then, to deference a reference (to get to its juicy content), you place the appropriate sigil in front of the reference (or the block that results in the reference). So, your loop would start with:

    foreach my $item (@$xpid_ref) {
    Furthermore, if you are looping over an array with
    foreach my $element (@array)
    don't use an index to get to the element! You already have it in your variant: $element. So, you'd write your loop as:
    foreach my $item (@$xpid_ref) { $return .= $item; }
    Of course, the entire function body can be reduced to a one-liner:
    return join "" => @{+shift}
    and then you can take the 'return' off as well.

    Abigail

Re: Help w passing array by ref
by liz (Monsignor) on Oct 10, 2003 at 16:20 UTC
    Almost right!
    sub makeSql { my @xpid = @{shift()}; ^^ ^ # dereference the array reference

    Perl 5 doesn't know automatically that it received a scalar reference and cannot automatically create an array out of that. You need to tell it yourself.

    Please note the parenthesis with shift. You also need these to disambiguate with a global array with the name "shift".

    Hope this helps.

    Liz

Re: Help w passing array by ref
by rlb3 (Deacon) on Oct 10, 2003 at 16:14 UTC
    I think this is what you are wanting to do. I hope
    this helps.

    sub makeSql { my $xpid = shift; my $return; my $i = 0; foreach my $item (@$xpid) { $return .= $xpid[$i]; $i++; } return $return; }

    rlb3
      Using a leading "r_" on references can help to keep track of things, mnemonic-wise:
      sub makeSql { my $r_xpid = shift; my $return = ""; $return .= $r_xpid->[$_] foreach 0 .. scalar @$r_xpid - 1; return $return; }
Re: Help w passing array by ref
by Not_a_Number (Prior) on Oct 10, 2003 at 17:04 UTC

    On top of perldoc perlreftut, you should find perldoc perllol and perldoc perldsc really useful.

    dave

Re: Help w passing array by ref
by EvdB (Deacon) on Oct 10, 2003 at 16:22 UTC

    You are passing the array to makeSQL as a ref here:

    my $sql = makeSql(\@xpid);
    However here you make an error:
    sub makeSql { my @xpid = shift; # <----------- error my $return; # try: my $xpid = shift my $i = 0; ^ foreach my $item (@xpid) { # <-- error $return .= $xpid[$i]; # <-- error # try: foreach my $item (@$xpid) ^ # try: $return .= $$xpid[$i]; ^
    The reference the is passed to the function should be stored in a scalar. When it then needs to be used as an array you dereference it with @$xpid and then again with $return .= $$xpid[$i];.

    --tidiness is the memory loss of environmental mnemonics