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

I would have thought these 2 expressions are equivalent but apparently they are not. Can someone explain to me why?

Thanks,

1) [[$q->param('at0')]]

2) \@{$q->param('at0')}

Updated Steve_p - added code tags

Replies are listed 'Best First'.
Re: Array Reference
by Roy Johnson (Monsignor) on Feb 11, 2005 at 00:38 UTC
    1. [something] creates an array, populates it with something, and returns a reference to it.
    2. \@something says that there is an array that already exists, just give me a reference to it.

    Caution: Contents may have been coded under pressure.
Re: Array Reference
by saintmike (Vicar) on Feb 10, 2005 at 23:39 UTC
    The first one copies the content of the array into a new, anonymous array and returns a reference to the new data structure. The second one returns a reference and is identical to $q->param('at0').
Re: Array Reference
by Sandy (Curate) on Feb 10, 2005 at 23:48 UTC
    I'm assuming that q->param{'at0'} is a reference to an array.
    #!/usr/bin/perl -w use strict; # array : assume address 123 my @a = qw(one two three); # reference to array in address 123 # (ARRAY(0x123) my $aa = \@a; # referencec to anonymous array containing # one element, the reference to array @a, # (ARRAY(0x123)) # assume $bb = ARRAY(0x789) my $bb = [$aa]; # @{$aa} returns the array at address 123 # - which is just array @a, # the \@{$aa} returns a reference to the # array at address 123. # - so $cc = ARRAY(0x123) my $cc = \@{$aa}; # results print "array a <@a>\n"; print "reference to array a <$aa>\n"; print "reference to anon array containing reference to array <$bb> +\n"; print "contents of array referred to by \$bb <@$bb>\n"; print "reference to the array referred to by \$aa <$cc>\n"; print "contents of array referred to by \$cc, or array a <@$cc>\n" +;
    Result
    array a <one two three> reference to array a <ARRAY(0x148bac)> reference to anon array containing reference to array <ARRAY(0x138a6c) +> contents of array referred to by $bb <ARRAY(0x148bac)> reference to the array referred to by $aa <ARRAY(0x148bac)> contents of array referred to by $cc, or array a <one two three>
    UPDATE Changed the word 'pointer' to 'reference', as per revdiablo's comment.

      References aren't pointers. They're similar, but not the same. Calling them pointers is potentially confusing, so I would advise against it.

        ok
Re: Array Reference
by artist (Parson) on Feb 10, 2005 at 23:42 UTC
    Assume that $q->param('at0') = 2; Now compare 2 and \@{2}
Re: Array Reference
by rhumbliner (Sexton) on Feb 11, 2005 at 04:54 UTC
    Thanks for all the responses. I appreciate the time you all took to provide an answer and the answers all pretty much confirm what I thought I already knew.

    Here's an excerpt from the documentation on the CGI::param method: "...param returns a list of all of the values if it is called in a list context and just the first value if it is called in a scalar context.". So I wanted to avoid copying the contents of $q->param('at0') to another location and then passing a reference to that new array. I just wanted to pass a reference to the existing array. Hence my desire to use option 2) instead of 1). But using option 2) returns the following runtime error: "Can't use string ("H&C05.01") as an ARRAY ref...". Just to clear up the nature of the beast a few prints may be useful:

    print Dumper($q->param('at0'))."\n"; # generates: $VAR1 = 'H&C05.01'; $VAR2 = 'SETT04.03';

    print Dumper([$q->param('at0')])."\n"; # generates: $VAR1 = [ 'H&C05.01', 'SETT04.03' ];

    print \@{$q->param('at0')}."\n"; # generates: Can't use string ("H&C05.01") as an ARRAY ref while "strict refs" in u +se at ...

    So I'm probably being really dense here, but I still don't understand why I can't just generate a reference to the existing array instead of copying the contents of the array to another location and generating a reference to that new location. Is it because I'm working with a method instead of a property of the CGI object?

    Still in the fog.

      Is it because I'm working with a method instead of a property of the CGI object?

      Yes. The param method decides to either give you a list (ie. copies of the values in the array it holds internally ) or just the first value (strange choice!) depending upon context. It doesn't provide a way of obtaining a reference to the internal array, so you cannot get at it--at least not through the 'front door' of the param method.

      However, this being Perl and all, if you use Dumper on the the CGI object itself, you see something like this:

      $VAR1 = bless( { 'at0' => [ '1', '2', '3' ], '.parameters' => [ 'at0' ], '.charset' => 'ISO-8859-1', '.fieldnames' => {}, 'escape' => 1 }, 'CGI' );

      So, if you're unconcerned with using the back door, then:

      #! perl -slw use strict; use Data::Dumper; use CGI; my $q = new CGI; my $at0ref = $q->{at0}; print $at0ref, " => @$at0ref"; __END__ P:\test>junk3 at0=1 at0=2 at0=3 ARRAY(0x195f6c4) => 1 2 3

      Caveat lector!


      Examine what is said, not who speaks.
      Silence betokens consent.
      Love the truth but pardon error.
        Well that does clear things up. In fact, I had been using the 'back door' but was looking for a clean way to use the 'front door'.

        Thanks for the insight.