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

Hallo,

I'm trying to pass an array slice by reference, but I'm getting odd things happen.

Here's some code snippets
@values=([some,things] , [1,2,3,4,5,6]); (a,b,c,d)=CalcMinAvgMaxSum(\@{${$values}[1]}[$start..$end]); sub CalcMinAvgMaxSum() { $ArrayOfValues_REF=@_; for $val (@{$ArrayOfValues_REF}) { ...do some stuff } }
But, I keep getting an error along the lines of

Can't use string ("a number") as an ARRAY ref while "strict refs" in use at ./scriptname (linenumber)

The linenumber given indicates it is the
for $val (@{ArrayOfValues_REF})

line that is the problem.

Thanks for you help and time ,
Matt.

Replies are listed 'Best First'.
Re: Passing references to array slices
by broquaint (Abbot) on Mar 17, 2004 at 17:11 UTC
    Since you can't create a reference to an array slice as such, since it returns a list, it's best just to wrap it in an anonymous array e.g
    CalcMinAvgMaxSum( [ @{ $values[1] }[ $start .. $end ] ] );
    See. tye's References quick reference and perlreftut for good starters on referencing + dereferencing in perl.
    HTH

    _________
    broquaint

Re: Passing references to array slices
by halley (Prior) on Mar 17, 2004 at 17:11 UTC
    As far as I know, you can't grab a reference to a slice. References can only refer to first-class datatypes (such as the things which can inhabit fields of a typeglob).

    A slice is not a first-class datatype, but a syntactic shortcut which implies certain simple logic, like, "by the way, please iterate over these elements."

    --
    [ e d @ h a l l e y . c c ]

Re: Passing references to array slices
by kvale (Monsignor) on Mar 17, 2004 at 17:21 UTC
    The second element in @values is already an array reference. In the first line of your sub, you are assigning the number of elements in @_, not the first element itself. Your code can be simplified as follows:
    my @values=([some,things] , [1,2,3,4,5,6]); my ($a, $b, $c, $d) = CalcMinAvgMaxSum( $values[1]); sub CalcMinAvgMaxSum() { my $ArrayOfValues_REF = shift; for my $val (@{$ArrayOfValues_REF}) { print "$val\n"; } }

    -Mark

Re: Passing references to array slices
by davido (Cardinal) on Mar 17, 2004 at 18:00 UTC
    An array slice is not a datastructure, it is simply a list of elements from the array. If you recall from the docs, when you do something like this:
    my $ref = \ (1, 2, 3); print ${$ref}, "\n";
    The output will be '3'. You've just created a reference to an anonymous scalar value, which happened to be the last value of the list. If you had said,
    my @ref = \ ( 1, 2, 3 ); print ${$_}, "\n" for @ref;
    Your output would be '123'. That's because the \ operator is distributive to each element in the list; and @ref receives as values three references, each to one of the anonymous scalar values in the list.


    Dave

Re: Passing references to array slices
by RMGir (Prior) on Mar 17, 2004 at 17:48 UTC
    You can't pass a ref to an array slice, but you CAN pass a list of refs to the slice members. This may or may not let you do what you need to do; I hope it helps.
    #!/usr/bin/perl -w use strict; my @x=0..10; sub dbl { foreach(@_){ $$_*=2 } } dbl(\(@x[1,2,3,5,6,7])); print join ",",@x; print "\n";

    Mike
Re: Passing references to array slices
by bageler (Hermit) on Mar 17, 2004 at 18:14 UTC
    your code is passing an arrayref, which is a scalar. $ArrayOfValues_REF is picking up @_, an array. $_[0] is your arrayref that you are passing, not @_. $ArrayOfValues_REF = shift should work.
Re: Passing references to array slices
by calin (Deacon) on Mar 17, 2004 at 19:23 UTC

    I don't know what you're really trying to do, but I foresee two possible scenarios:

    Pass a reference to a new array containing copies of the scalars in the slice. It's simple and clear:

    $ perl my @a = qw/a b c d e/; sub printthese { local $, = ', '; print @{$_[0]}; print "\n"; } printthese( [ @a[0, 2, 4] ]); ^D a, c, e

    Pass a reference to a new array containing aliases to the scalars in the slice, so you can modify them

    $ perl my @a = qw/1 2 3 4 5/; sub zerothese { $_ = 0 for @{$_[0]}; } zerothese( &{sub {\@_}} (@a[0, 2, 4]) ); print join ', ', @a; print "\n"; ^D 0, 2, 0, 4, 0
      Thankyou to you all for the help;

      I discovered the problem was with this line of code;
      $ArrayOfValues_REF=@_;
      it should have read
      ($ArrayOfValues_REF)=@_;

      Peace and Love,
      Matt.