What are the consequences of "$scalar = #array[n]"? - arrays

use warnings;
my #array = (0, 1);
my $scalar1 = $array[0];
my $scalar2 = #array[0];
if($scalar1 == $scalar2) {
print "scalars are equal\n";
}
Here's the output when I run /usr/bin/perl5.10.1 test.pl:
Scalar value #array[0] better written as $array[0] at test.pl line 4.
scalars are equal
I'm concerned about that warning.

You can look up all warning messages in perldoc perldiag, which explains the consequences:
(W syntax) You've used an array slice (indicated by #) to select a
single element of an array. Generally
it's better to ask for a scalar value
(indicated by $). The difference is
that $foo[&bar] always behaves like a
scalar, both when assigning to it and
when evaluating its argument, while
#foo[&bar] behaves like a list when
you assign to it, and provides a list
context to its subscript, which can do
weird things if you're expecting only
one subscript.
On the other hand, if you were actually hoping to treat the array
element as a list, you need to look
into how references work, because Perl
will not magically convert between
scalars and lists for you. See
perlref.
Similarly, you can use diagnostics; to get this verbose explanation of the warning message.
A third way is to use the splain utility.

It is possible to take an array slice of a single element:
#fruits[1]; # array slice of one element
but this usually means that you’ve made a mistake and Perl will warn you that what you really
should be writing is:
$fruits[1];

There are no consequences for that usage. I think the purpose is to help you avoid the consequences when a warning can't be issued.
Slices on the LHS of "=" cause =" to be a list assignment operator.
$ perl -E'sub f { return 4; } my $x = $a[1] = f(); say $x'
4
$ perl -E'sub f { return 4; } my $x = #a[1] = f(); say $x'
1
Slices evaluate the index in list context.
$ perl -E'sub f { my #i = 3; #i } #a=qw( a b c d e f ); say #a[f()]'
d
$ perl -E'sub f { my #i = 3; #i } #a=qw( a b c d e f ); say $a[f()]'
b

Related

perl6 What is a quick way to de-select array or list elements?

To select multiple elements from an array in perl6, it is easy: just use a list of indices:
> my #a = < a b c d e f g >;
> #a[ 1,3,5 ]
(b d f)
But to de-select those elements, I had to use Set:
> say #a[ (#a.keys.Set (-) (1,3,5)).keys.sort ]
(a c e g)
I am wondering if there is an easier way because the arrays I use are often quite large?
sub infix:<not-at> ($elems, #not-ats) {
my $at = 0;
flat gather for #not-ats -> $not-at {
when $at < $not-at { take $at++ xx $not-at - $at }
NEXT { $at++ }
LAST { take $at++ xx $elems - $not-at - 1 }
}
}
my #a = < a b c d e f g >;
say #a[ * not-at (1, 3, 5) ]; # (a c e g)
I think the operator code is self-explanatory if you know each of the P6 constructs it uses. If anyone would appreciate an explanation of it beyond the following, let me know in the comments.
I'll start with the two aspects that generate the call to not-at.
* aka Whatever
From the Whatever doc page:
When * is used in term position, that is, as an operand, in combination with most operators, the compiler will transform the expression into a closure of type WhateverCode
* is indeed used in the above as an operand. In this case it's the left argument (corresponding to the $elems parameter) of the infix not-at operator that I've just created.
The next question is, will the compiler do the transform? The compiler decides based on whether the operator has an explicit * as the parameter corresponding to the * argument. If I'd written * instead of $elems then that would have made not-at one of the few operators that wants to directly handle the * and do whatever it chooses to do and the compiler would directly call it. But I didn't. I wrote $elems. So the compiler does the transform I'll describe next.
The transform builds a new WhateverCode around the enclosing expression and rewrites the Whatever as "it" aka the topic aka $_ instead. So in this case it turns this:
* not-at (1,3,5)
into this:
{ $_ not-at (1,3,5) }
What [...] as a subscript does
The [...] in #a[...] is a Positional (array/list) subscript. This imposes several evaluation aspects, of which two matter here:
"it" aka the topic aka $_ is set to the length of the list/array.
If the content of the subscript is a Callable it gets called. The WhateverCode generated as explained above is indeed a Callable so it gets called.
So this:
#a[ * not-at (1,3,5) ]
becomes this:
#a[ { $_ not-at [1,3,5] } ]
which turns into this:
#a[ { infix:not-at(7, [1,3,5]) } ]
Given the indexer wants the elements to extract, we could solve this by turning the list of elements to exclude into a list of ranges of elements to extract. That is, given:
1, 3, 5
We'd produce something equivalent to:
0..0, 2..2, 4..4, 6..Inf
Given:
my #exclude = 1, 3, 5;
We can do:
-1, |#exclude Z^..^ |#exclude, Inf
To break it down, zip (-1, 1, 3, 5) with (1, 3, 5, Inf), but using the range operator with exclusive endpoints. This results in, for the given example:
(-1^..^1 1^..^3 3^..^5 5^..^Inf)
Which is equivalent to the ranges I mentioned above. Then we stick this into the indexer:
my #a = <a b c d e f g>
my #exclude = 1, 3, 5;
say #a[-1, |#exclude Z^..^ |#exclude, Inf].flat
Which gives the desired result:
(a c e g)
This approach is O(n + m). It will probably work out quite well if there array is long, but the number of things to exclude is comparatively small, since it only produces the Range objects needed for the indexing, and then indexing by range is relatively well optimized.
Finally, should the flat on the outside be considered troublesome, it's also possible to move it inside:
#a[{ flat -1, |#exclude Z^..^ |#exclude, $_ }]
Which works because the block is passed the number of elements in #a.
Here's another option:
my #a = < a b c d e f g >;
say #a[#a.keys.grep(none(1, 3, 5))];
But all in all, arrays aren't optimized for this use case. They are optimized for working with a single element, or all elements, and slices provide a shortcut for (positively) selecting several elements by key.
If you tell us about the underlying use case, maybe we can recommend a more suitable data structure.
This might be slow for big arrays, but it's logically the closer to what you're looking for:
my #a = <a b c d>;
say (#a ⊖ #a[0,1]).keys; # (c d)
It's basically the same solution you proposed at the beginning, using set difference, except it's using it on the whole array instead of on the indices. Also, in some cases you might use the set directly; it depends on what you want to do.
#raiphs solution combined with #Jonathan Worthington 's:
The operator should be very efficient for huge numbers and large #not-ats lists as it returns a list of ranges, and it even creates that list of ranges lazily. For the #not-ats it supports integers and ranges with included and excluded bounds and infinity. But it has to be ascending.
The $elems can be a Range or an Int. It is interpreted as .Int as in Jonathan Worthington's solution to support (but needs a .flat applying it to array slicing - the price of performance for the lazy operator - this could be changed by using flat gather instead of lazy gather in the 2nd line)
#a[ (* not-at (1, 3, 5)).flat ];
or newly support
#a[ (* not-at (1, 3^ .. 5, 8 .. 8, 10, 14 .. ^18, 19 .. *)).flat ];
The performance improvements can be seen, when not slicing the array at once, but operating on parts of the array, optimally with multithreading.
sub infix:<not-at> ($elems, #not-ats) {
lazy gather {
my $at = 0;
for #not-ats { # iterate over #not-ats ranges
my ($stop, $continue) = do given $_ {
when Int { succeed $_, $_ } # 5
when !.infinite { succeed .int-bounds } # 3..8 | 2^..8 | 3..^9 | 2^..^9
when !.excludes-min { succeed .min, $elems.Int } # 4..*
default { succeed .min + 1, $elems.Int } # 3^..*
}
take $at .. $stop - 1 if $at < $stop; # output Range before current $not-at range
$at = $continue + 1; # continue after current $not-at range
}
take $at .. $elems.Int - 1 if $at < $elems; # output Range with remaining elements
}
}

Assigning to a slice of a 3D array using the range operator

I have a 3 dimensional array. I want to set three elements of it like this:
$array[$x][$y][0 .. 2] = (0, 1, 2);
but perl tells me:
Useless use of a constant (1) in void context
In array context:
#array[$x][$y][0 .. 2] = (0, 1, 2);
but perl tells me:
syntax error near "]["
presumably meaning that it expects me to give it two indices and then assign to the third dimension as a separate array? However, on this page, under Example: Assignment Using Array Slices, it suggests that it is possible to assign to a slice using the range operator where it says:
#array1[1..3] = #array2[23..25];
How can I assign to a slice of the array like this, or do I have to assign each index individually?
You need to dereference the inner array:
#{ $arr[$x][$y] }[ 0 .. 2 ] = (0, 1, 2);
$array[$x][$y][0..2] isn't a slice; it's just an element lookup.
When you attempted to change it into a slice, you sliced the wrong array. You sliced #arr instead of #{ $arr[$x][$y] }.
The key here is to realize that there's no such thing as 3d arrays in Perl. What you have is an array of references to arrays of references to array, which is colloquially called array of array of array, and often abbreviated to AoAoA.
Array slices have the following syntax:
#NAME[LIST]
#BLOCK[LIST]
#$REF[LIST]
EXPR->#[LIST][1]
You could use any of the following:
The first syntax can't be used since the array to slice doesn't have a name.
#{ $array[$x][$y] }[0..2] = 0..2;
my $ref = $array[$x][$y]; #$ref[0..2] = 0..2;
$array[$x][$y]->#[0..2] = 0..2;[1]
See Dereferencing Syntax.
Requires Perl 5.24+. Available in Perl 5.20+ by adding both use feature qw( postderef ); and no warnings qw( experimental::postderef );.

Count Perl array size

I'm trying to print out the size of my array. I've followed a few other questions like this one on Stack Overflow. However, I never get the result I want.
All I wish for in this example is for the value of 3 to be printed as I have three indexes. All I get, from both print methods is 0.
my #arr;
$arr{1} = 1;
$arr{2} = 2;
$arr{3} = 3;
my $size = #arr;
print $size; # Prints 0
print scalar #arr; # Prints 0
What am I doing wrong, and how do I get the total size of an array when declared and populated this way?
First off:
my #arr;
$arr{1} = 1;
$arr{2} = 2;
$arr{3} = 3;
is nonsense. {} is for hash keys, so you are referring to %arr not #arr. use strict; and use warnings; would have told you this, and is just one tiny fragment of why they're considered mandatory.
To count the elements in an array, merely access it in a scalar context.
print scalar #arr;
if ( $num_elements < #arr ) { do_something(); }
But you would need to change your thing to
my #arr;
$arr[1] = 1;
$arr[2] = 2;
$arr[3] = 3;
And note - the first element of your array $arr[0] would be undefined.
$VAR1 = [
undef,
1,
2,
3
];
As a result, you would get a result of 4. To get the desired 'count of elements' you would need to filter the undefined items, with something like grep:
print scalar grep {defined} #arr;
This will take #arr filter it with grep (returning 3 elements) and then take the scalar value - count of elements, in this case 3.
But normally - you wouldn't do this. It's only necessary because you're trying to insert values into specific 'slots' in your array.
What you would do more commonly, is use either a direct assignment:
my #arr = ( 1, 2, 3 );
Or:
push ( #arr, 1 );
push ( #arr, 2 );
push ( #arr, 3 );
Which inserts the values at the end of the array. You would - if explicitly iterating - go from 0..$#arr but you rarely need to do this when you can do:
foreach my $element ( #arr ) {
print $element,"\n";
}
Or you can do it with a hash:
my %arr;
$arr{1} = 1;
$arr{2} = 2;
$arr{3} = 3;
This turns your array into a set of (unordered) key-value pairs, which you can access with keys %arr and do exactly the same:
print scalar keys %arr;
if ( $elements < keys %arr ) { do_something(); }
In this latter case, your hash will be:
$VAR1 = {
'1' => 1,
'3' => 3,
'2' => 2
};
I would suggest this is bad practice - if you have ordered values, the tool for the job is the array. If you have 'key' values, a hash is probably the tool for the job still - such as a 'request ID' or similar. You can typically tell the difference by looking at how you access the data, and whether there are any gaps (including from zero).
So to answer your question as asked:
my $size = #arr;
print $size; # prints 0
print scalar #arr; # prints 0
These don't work, because you never insert any values into #arr. But you do have a hash called %arr which you created implicitly. (And again - use strict; and use warnings; would have told you this).
You are initializing a hash, not an array.
To get the "size" of your hash you can write.
my $size = keys %arr;
I just thought there should be an illustration of your code run with USUW (use strict/use warnings) and what it adds to the troubleshooting process:
use strict;
use warnings;
my #arr;
...
And when you run it:
Global symbol "%arr" requires explicit package name (did you forget to declare "my %arr"?) at - line 9.
Global symbol "%arr" requires explicit package name (did you forget to declare "my %arr"?) at - line 10.
Global symbol "%arr" requires explicit package name (did you forget to declare "my %arr"?) at - line 11.
Execution of - aborted due to compilation errors.
So USUW.
You may be thinking that you are instantiating an element of #arr when you are typing in the following code:
$arr{1} = 1;
However, you are instantiating a hash doing that. This tells me that you are not using strict or you would have an error. Instead, change to brackets, like this:
$arr[1] = 1;

What is the difference between lists and arrays?

On this page, it shows how to initialize an array, and if you scroll down a bit, under the section called "The Lists" it "explains" what lists are and how they're different from arrays.
Except it uses an example that's just exactly the same as declaring an array, and doesn't explain it whatsoever.
What is the difference?
Take a look at perldoc -q "list and an array". The biggest difference is that an array is a variable, but all of Perl's data types (scalar, array and hash) can provide a list, which is simply an ordered set of scalars.
Consider this code
use strict;
use warnings;
my $scalar = 'text';
my #array = (1, 2, 3);
my %hash = (key1 => 'val1', key2 => 'val2');
test();
test($scalar);
test(#array);
test(%hash);
sub test { printf "( %s )\n", join ', ', #_ }
which outputs this
( )
( text )
( 1, 2, 3 )
( key2, val2, key1, val1 )
A Perl subroutine takes a list as its parameters. In the first case the list is empty; in the second it has a single element ( $scalar); in the third the list is the same size as #array and contains ( $array[0], $array[1], $array[2], ...), and in the last it is twice as bug as the number of elements in %hash, and contains ( 'key1', $hash{key1}, 'key2', $hash{key2}, ...).
Clearly that list can be provided in several ways, including a mix of scalar variables, scalar constants, and the result of subroutine calls, such as
test($scalar, $array[1], $hash{key2}, 99, {aa => 1, bb => 2}, \*STDOUT, test2())
and I hope it is clear that such a list is very different from an array.
Would it help to think of arrays as list variables? There is rarely a problem distinguishing between scalar literals and scalar variables. For instance:
my $str = 'string';
my $num = 99;
it is clear that 'string' and 99 are literals while $str and $num are variables. And the distinction is the same here:
my #numbers = (1, 2, 3, 4);
my #strings = qw/ aa bb cc dd /;
where (1, 2, 3, 4) and qw/ aa bb cc dd / are list literals, while #numbers and #strings are variables.
Actually, this question is quite well answered in Perl's FAQ. Lists are (one of) methods to organize the data in the Perl source code. Arrays are one type of storing data; hashes are another.
The difference is quite obvious here:
my #arr = (4, 3, 2, 1);
my $arr_count = #arr;
my $list_count = (4, 3, 2, 1);
print $arr_count, "\n"; # 4
print $list_count; # 1
At first sight, there are two identical lists here. Note, though, that only the one that is assigned to #arr variable is correctly counted by scalar assignment. The $list_count stores 1 - the result of evaluating expression with comma operator (which basically gives us the last expression in that enumeration - 1).
Note that there's a slight (but very important) difference between list operators/functions and array ones: the former are kind-of omnivores, as they don't change the source data, the latter are not. For example, you can safely slice and join your list, like this:
print join ':', (4,2,3,1)[1,2];
... but trying to 'pop' it will give you quite a telling message:
pop (4, 3, 2, 1);
### Type of arg 1 to pop must be array (not list)...
An array is a type of variable. It contains 0 or more scalars at monotonously increasing indexes. For example, the following creates array #a:
my #a;
Being variables, you can manipulate arrays. You can add elements, change the values of elements, etc.
"List" means many things. The two primary uses for it are to refer to list values and instances of the list operator.
A list value is an ordered collection of zero or more scalars on the stack. For example, the sub in the following code returns a list to be assigned to #a (an array).
my #a = f();
List values can't be manipulated; they are absorbed in whole by any operator to which they are passed. They are just how values are passed between subs and operators.
The list operator (,) is an N-ary operator* that evaluates each of its operands in turn. In list context, the list operator returns a list consisting of an amalgamation of the lists returned by its operands. For example, the list operator in the following snippet returns a list value consisting of all the elements of arrays #a and #b:
my #c = ( #a, #b );
(By the way, parens don't create lists. They're just there to override precedence.)
You cannot manipulate a list operator since it's code.
* — The docs say it's a binary operator (at least in scalar context), but it's not true.
Simple demonstration of difference.
sub getarray{ my #x = (2,4,6); return #x; }
sub getlist { return (2,4,6); }
Now, if you do something like this:
my #a = getarray();
my #b = getlist();
Then #a and #b will both contain the same value - the list (2,4,6). However, if you do this:
my $a = getarray();
my $b = getlist();
Then $a will contain the value 3, while $b will contain the value 6.
So yes, you can say that arrays are variables containing list values, but that doesn't tell the whole story, because arrays and literal lists behave quite differently at times.
Lists are comma-separated values (csv) or expressions (cse) . Arrays (and hashes) are containers.
One can initialize an array or hash by a list:
#a = ("profession", "driver", "salary", "2000");
%h = ("profession", "driver", "salary", "2000");
One can return a list:
sub f {
return "moscow", "tel-aviv", "madrid";
}
($t1, $t2, $t3) = f();
print "$t1 $t2 $t3\n";
($t1, $t2, $t3) is a list of scalar containers $t1, $t2, $t3.
Lists are a form of writing perl expressions (part of syntax) while arrays are data structures (memory locations).
The difference between lists and arrays confuses many. Perl itself got it wrong by misnaming its builtin function wantarray(): "This function should have been named wantlist() instead." There is an answer in perlfaq4, "What is the difference between a list and an array?", but it did not end my confusion.
I now believe these to be true:
An array in scalar context becomes a count of its elements.
The comma operator in scalar context returns the last element.
You can't make a reference to a list; \(2, 4, 6) returns a list of references to the scalars in the list. You can use [2, 4, 6] to make a reference to an anonymous array.
You can index a list (to get its nth element) without making an array if you make a list slice, so (2, 4, 6)[1] is 4.
But what if I want to count the elements in a list, or get the last element of an array? Should I convert between arrays and lists somehow?
You can always convert a list to an array with [...] syntax. One way to count the elements in a list is to make an anonymous array, then immediately dereference it in scalar context, like so:
sub list { return qw(carrot stick); }
my $count = #{[list()]};
print "Count: $count\n"; # Count: 2
Another way is to use the list assignment operator, like so:
sub list { return qw(carrot stick); }
my $count = (()=list());
print "Count: $count\n"; # Count: 2
There is no array in this code, but the list assignment operator returns the number of things being assigned. I assign them to an empty list of variables. In code golf, I write ()=$str=~/reg/g to count the regular expression matches in some string.
You need not convert an array to a list, because an array in list context is already a list. If you want the last element of an array, just say $array[-1].
The comma operator would return the last element of a list, but I can't use it to get the last element of an array. If I say ((),#array) in scalar context, then #array is in scalar context and I get the count.
You need not make an array to index a list. You can make an anonymous array, as in [list()]->[1], or you can make a list slice, as in (list())[1]. I had trouble with list slices because they have different syntax. A list slice needs parentheses! In C or Python or Ruby, func()[1] would do the array index on the function's return value, but in Perl, func()[1] is a syntax error. You must say (func())[1].
For example, I want to print the 3rd highest number in array. Because I'm lazy, I sort the array and take the 3rd last element:
my #array = (112, 101, 114, 108, 32, 104, 97, 99, 107);
print +(sort { $a <=> $b } #array)[-3], "\n"; # prints 108
The unary + prevents the print() function stealing my parentheses.
You can use a list slice on an array, as in (#array)[1]. This works because an array is a list. The difference between lists and arrays is that arrays can do $array[1].
An Array Vs A List
A list is a different kind of data structure from an array.
The biggest difference is in the idea of direct access Vs sequential access. Arrays allow both; direct and sequential access, while lists allow only sequential access. And this is because the way that these data structures are stored in memory.
In addition, the structure of the list doesn’t support numeric index like an array is. And, the elements don’t need to be allocated next to each other in the memory like an array is.
Arrays
An array is an ordered collection of items, where each item inside the array has an index.
here my answer about sigils and context
but main difference is this:
arrays have a scalar-context-value like count of elements.
lists have a scalar-context-value like LAST element in list.
so, you need to know about goat-operator: =()=.
Usage?
perl -e '$s =()= qw(a b c); print $s' # uh? 3? (3 elements, array context)
perl -e '$s = qw(a b cLastElementThatYouSee); print $s' # uh? cLastElementThatYouSee? (list context, last element returned)
as you see, =()= change context to array

Perl subroutines and arrays

I'm just starting out Perl (about 15 minutes ago) using a tutorial online. I made a small subroutine to test a few Perl features and would like to know if it is possible to determine at runtime if parameters that were passed to the sub' call are arrays or scalars. Let's use the sub I wrote as an example:
#!/usr/bin/perl
sub somme_prod {
if (scalar(#_) > 1) {
$facteur = shift(#_);
foreach my $nb (#_) {
$resultat += $nb
}
return ($resultat * $facteur);
}
else {
return "ERREUR";
}
}
print somme_prod(2, 2, 3, 7);
This is a basic sum-product subroutine which does exactly what its name says. Now, would it be possible to modify this subroutine to allow for a mix of arrays and scalars like this ?
somme_prod(2, (2,3), 7);
somme_prod(2, (2,3,7));
#...
Also, any comment on the style of Perl coding demonstrated here is much welcome. I have a background of amateur C++ coding so I may not be thinking in Perl.
Edit: I'm so sorry. I actually tried it after posting and it seems that Perl does process my sub as I want it to. Now I guess my question would be more "how does Perl know how to process this" ?
Edited code for a more Perl-ish version.
Yes; in Perl you can create references to arrays (or hashes, or anything else) to stuff several values into a single parameter.
For example:
somme_prod(2, [2, 3], 7);
...would resolve to:
sub somme_prod {
foreach my $arg (#_) {
if (ref($arg) eq 'ARRAY') {
my #values = #$arg; # dereference, e.g. [2, 3] -> (2, 3)
. . .
} else {
# single value, e.g. "2" or "7"
}
}
}
You can read the page perldoc perlref to learn all about references.
Perl handles lists and arrays differently, and a useful document for you to read is What is the difference between a list and an array?
Perl will always flatten nested lists (and so arrays within lists) so
my #data1 = (2, (2, 3), 7);
or
my #data2 = (2, 3);
my #data1 = (2, #data2, 7);
is equivalent to
my #data1 = (2, 2, 3, 7);
As Kevin says, if you want nested arrays you have to place an array reference in the place where the sublist appears. Because a reference is a scalar it won't get expanded.
Your subroutine is fine, but using some de-facto standards would help others to follow your program. Firstly the convention is that a subroutine will return undef if there is an error, so that you can write
sous_routine($p1, $p2) or die "Erreur";
In this case the possibility that zero is a valid result spoils this, but it is still best to stick to the rules. A plain return without a parameter indicates an error
A little bit of tidying up and using unless and if as statement modifiers gives this
sub somme_prod {
return unless #_ > 1;
my $facteur = shift;
my $somme = 0;
$somme += $_ for #_;
return $somme * $facteur;
}
print somme_prod(2, 2, 3, 7);
You've known Perl for 15 minutes? Forget about references for now.
Basically, everything passed to a subroutine is an array. In fact, it's stored in an array called #_.
# /usr/bin/env perl
use strict; #ALWAYS USE!
use warnings; #ALWAYS USE!
my #array = qw(member1 member2 member3 member4);
foo(#array, 'scalar', 'scalar', 'scalar');
sub foo {
print "My input is " . join (":", #_) . "\n";
This will print:
my input is member1:member2:member3:member4:scalar:scalar:scalar
There is no way to tell which entries are from an array and which are from a scalar. As far as your subroutine is concerned, they're all members of the array #_.
By the way, Perl comes with a command called perldoc. When someone says to see perlref, you can type in perldoc perlref at the command line and see the documentation. You can also go to the site http://perldoc.perl.org which will also contain the same information found in the perldoc command.
Now about references....
A data element of a Perl array or the value of a hash can only contain a single value. That could be a string, it could be a real number, it could be an integer, and it could be a reference to another Perl data structure. That's where all the fun and money is.
For example, the same subroutine foo above could have taken this information:
foo(\#array, 'scalar', 'scalar', 'scalar'); #Note the backslash!
In this case, you're not passing in the values of #array into foo. Instead, a reference to the array is passed as the first data element of #_. If you attempted to print out $_[0], you'd get something like ARRAY:6E43832 which says the data element is an array and where it's located in memory.
Now, you can use the ref function to see whether an piece of data is a reference and the type of reference it is:
sub foo {
foreach my $item (#_) {
if (ref $item eq 'ARRAY') {
print "This element is a reference to an array\n";
}
elsif (ref $item eq 'HASH') {
print "This element is a reference to a hash\n";
}
elsif (ref $item) { #Mysterious Moe Reference
print "This element is a reference to a " . lc (ref $item) . "\n";
}
else {
print "This element is a scalar and it's value is '$item'\n";
}
}
}
Of course, your reference to an array might be an array that contains references to hashes that contain references to arrays and so on. There's a module that comes with Perl called Data::Dumper (you can use perldoc to see information about it) that will print out the entire data structure.
This is how object orient Perl works, so it's really quite common to have references to other Perl data structures embedded in a piece of Perl data.
Right now, just get use to basic Perl and how it works. Then, start looking at the various tutorials about Perl references in Perldoc.

Resources