perl 101, getting length of array from using $ on the array variable - perl

I was expecting this to give the length of the array. Since I thought $mo implied scalar context.
But instead, I get the error :
Global symbol "$mo" requires explicit package name at ./a.pl line 7.
#! /usr/bin/perl
use strict;
use warnings;
my #mo = (3,4,5);
print( $mo);
UPDATE::
I thought mo is the variable and the sigil $ on $mo is using scalar context. My question is more on the sigil then actually getting the length.

In order to get the number of elements in #mo use scalar #mo.
my $num_elements = scalar #mo;
You can omit the scalar when the context dictates that it must be scalar, such as in a comparison:
if ($count < #mo) { print "$count is less than the number of elements" }
You can also use $#mo, which is the index of the last element (generally one less than the number of elements).
my $last_index = $#mo;
This is useful when you are iterating through an array and need the array index:
for (0..$#mo)
{
print "Index $_ is $mo[$_]\n";
}
The $mo form is used when obtaining an element of the array:
my $second_element = $mo[1];
$mo just by itself is a totally separate variable (though you probably shouldn't create such a variable, as it would be confusing).

You are trying to print a scalar variable $mo which does not exist. You need to use the array name in scalar context as:
my #mo = (3,4,5);
print scalar #mo;
Another way is to use $#mo which would return the largest index in the array which in your case is 2.

You may get length of an array as
my $mo = #mo;
print $mo;
my $mo = scalar (#mo);
print $mo;
my $mo = $#mo + 1; print $mo;

Related

Why array counter returns a smaller number? [duplicate]

I seem to have come across several different ways to find the size of an array. What is the difference between these three methods?
my #arr = (2);
print scalar #arr; # First way to print array size
print $#arr; # Second way to print array size
my $arrSize = #arr;
print $arrSize; # Third way to print array size
The first and third ways are the same: they evaluate an array in scalar context. I would consider this to be the standard way to get an array's size.
The second way actually returns the last index of the array, which is not (usually) the same as the array size.
First, the second ($#array) is not equivalent to the other two. $#array returns the last index of the array, which is one less than the size of the array.
The other two (scalar #arr and $arrSize = #arr) are virtually the same. You are simply using two different means to create scalar context. It comes down to a question of readability.
I personally prefer the following:
say 0+#array; # Represent #array as a number
I find it clearer than
say scalar(#array); # Represent #array as a scalar
and
my $size = #array;
say $size;
The latter looks quite clear alone like this, but I find that the extra line takes away from clarity when part of other code. It's useful for teaching what #array does in scalar context, and maybe if you want to use $size more than once.
This gets the size by forcing the array into a scalar context, in which it is evaluated as its size:
print scalar #arr;
This is another way of forcing the array into a scalar context, since it's being assigned to a scalar variable:
my $arrSize = #arr;
This gets the index of the last element in the array, so it's actually the size minus 1 (assuming indexes start at 0, which is adjustable in Perl although doing so is usually a bad idea):
print $#arr;
This last one isn't really good to use for getting the array size. It would be useful if you just want to get the last element of the array:
my $lastElement = $arr[$#arr];
Also, as you can see here on Stack Overflow, this construct isn't handled correctly by most syntax highlighters...
To use the second way, add 1:
print $#arr + 1; # Second way to print array size
All three give the same result if we modify the second one a bit:
my #arr = (2, 4, 8, 10);
print "First result:\n";
print scalar #arr;
print "\n\nSecond result:\n";
print $#arr + 1; # Shift numeration with +1 as it shows last index that starts with 0.
print "\n\nThird result:\n";
my $arrSize = #arr;
print $arrSize;
Example:
my #a = (undef, undef);
my $size = #a;
warn "Size: " . $#a; # Size: 1. It's not the size
warn "Size: " . $size; # Size: 2
The “Perl variable types” section of the perlintro documentation contains
The special variable $#array tells you the index of the last element of an array:
print $mixed[$#mixed]; # last element, prints 1.23
You might be tempted to use $#array + 1 to tell you how many items there are in an array. Don’t bother. As it happens, using #array where Perl expects to find a scalar value (“in scalar context”) will give you the number of elements in the array:
if (#animals < 5) { ... }
The perldata documentation also covers this in the “Scalar values” section.
If you evaluate an array in scalar context, it returns the length of the array. (Note that this is not true of lists, which return the last value, like the C comma operator, nor of built-in functions, which return whatever they feel like returning.) The following is always true:
scalar(#whatever) == $#whatever + 1;
Some programmers choose to use an explicit conversion so as to leave nothing to doubt:
$element_count = scalar(#whatever);
Earlier in the same section documents how to obtain the index of the last element of an array.
The length of an array is a scalar value. You may find the length of array #days by evaluating $#days, as in csh. However, this isn’t the length of the array; it’s the subscript of the last element, which is a different value since there is ordinarily a 0th element.
From perldoc perldata, which should be safe to quote:
The following is always true:
scalar(#whatever) == $#whatever + 1;
Just so long as you don't $#whatever++ and mysteriously increase the size or your array.
The array indices start with 0.
and
You can truncate an array down to nothing by assigning the null list () to it. The following are equivalent:
#whatever = ();
$#whatever = -1;
Which brings me to what I was looking for which is how to detect the array is empty. I found it if $#empty == -1;
There are various ways to print size of an array. Here are the meanings of all:
Let’s say our array is my #arr = (3,4);
Method 1: scalar
This is the right way to get the size of arrays.
print scalar #arr; # Prints size, here 2
Method 2: Index number
$#arr gives the last index of an array. So if array is of size 10 then its last index would be 9.
print $#arr; # Prints 1, as last index is 1
print $#arr + 1; # Adds 1 to the last index to get the array size
We are adding 1 here, considering the array as 0-indexed. But, if it's not zero-based then, this logic will fail.
perl -le 'local $[ = 4; my #arr = (3, 4); print $#arr + 1;' # prints 6
The above example prints 6, because we have set its initial index to 4. Now the index would be 5 and 6, with elements 3 and 4 respectively.
Method 3:
When an array is used in a scalar context, then it returns the size of the array
my $size = #arr;
print $size; # Prints size, here 2
Actually, method 3 and method 1 are same.
Use int(#array) as it threats the argument as scalar.
To find the size of an array use the scalar keyword:
print scalar #array;
To find out the last index of an array there is $# (Perl default variable). It gives the last index of an array. As an array starts from 0, we get the size of array by adding one to $#:
print "$#array+1";
Example:
my #a = qw(1 3 5);
print scalar #a, "\n";
print $#a+1, "\n";
Output:
3
3
As numerous answers pointed out, the first and third way are the correct methods to get the array size, and the second way is not.
Here I expand on these answers with some usage examples.
#array_name evaluates to the length of the array = the size of the array = the number of elements in the array, when used in a scalar context.
Below are some examples of a scalar context, such as #array_name by itself inside if or unless, of in arithmetic comparisons such as == or !=.
All of these examples will work if you change #array_name to scalar(#array_name). This would make the code more explicit, but also longer and slightly less readable. Therefore, more idiomatic usage omitting scalar() is preferred here.
my #a = (undef, q{}, 0, 1);
# All of these test whether 'array' has four elements:
print q{array has four elements} if #a == 4;
print q{array has four elements} unless #a != 4;
#a == 4 and print q{array has four elements};
!(#a != 4) and print q{array has four elements};
# All of the above print:
# array has four elements
# All of these test whether array is not empty:
print q{array is not empty} if #a;
print q{array is not empty} unless !#a;
#a and print q{array is not empty};
!(!#a) and print q{array is not empty};
# All of the above print:
# array is not empty

Using string as array index in Perl

I have run into a strange behavior in Perl that I haven't been able to find documentation for. If I (by accident) use a string as an index in an array I get the first item of the array and not undef as I would have expected.
$index = "Some string";
#array = qw(one two three);
$item = $array[$index];
print "item: " . $item;
I expected to get item: as output, but instead I get item: one. I assume that because the string doesn't start with a number it's "translated" to 0 and hence giving me the first item in the array. If the string starts with a number that part of the string seems to be used as the index.
Is this to be expected, and is there any documentation describing how strings (e.g. "2strings") are interpreted as numbers in Perl?
Array index imposes numeric context. The string "Some string" in numeric context is equal to 0.
Under warnings, Perl will complain
Argument "Some string" isn't numeric in array or hash lookup at ...
Array indexes must be integers, so non-integer values are converted to integers.
The string one produces the number 0, as well as the following warning:
Argument "Some string" isn't numeric in array or hash lookup
This concept is found throughout Perl. For the same reason, arguments to addition and multiplication will similarly be converted to numbers. And values used as hash keys will be converted to strings. Dereferencing undef scalars even produces the necessary value and reference in a process called autovivification!
$ perl -Mv5.10 -e'
my $ref;
say $ref // "[undef]";
$ref->[1] = 123;
say $ref // "[undef]";
'
[undef]
ARRAY(0x560b653ae4b8)
As you can see, an array and a reference to that array were spontaneously created in the above program because they were needed.
The lesson to take: Always use use strict; use warnings;.

Why does perl only dereference the last index when the range operator is used?

I have an array, #array, of array references. If I use the range operator to print elements 1 through 3 of #array, print #array[1..3], perl prints the array references for elements 1 through 3.
Why when I try to dereference the array references indexed between 1 and 3, #{#array[1..3]}, perl only dereferences and prints out the last element indexed in the range operator?
Is there a way to use the range operator while dereferencing an array?
Example Code
#!/bin/perl
use strict;
use warnings;
my #array = ();
foreach my $i (0..10) {
push #array, [rand(1000), int(rand(3))];
}
foreach my $i (#array) {
print "#$i\n";
}
print "\n\n================\n\n";
print #{#array[1..3]};
print "\n\n================\n\n";
From perldata:
Slices in scalar context return the last item of the slice.
#{ ... } dereferences a scalar value as an array, this implies that the value being dereferenced is in scalar context. From the perldata quote above we know that this will return the last element. Therefore the result is the last element.
A more reasonable approach would be to loop through your slice and print each individual array reference:
use strict;
use warnings;
use feature qw(say);
my #array_of_arrayrefs = (
[qw(1 2 3)],
[qw(4 5 6)],
[qw(7 8 9)],
[qw(a b c)],
);
foreach my $aref ( #array_of_arrayrefs[1..3] ) {
say join ',', #$aref;
}
#{#array[1..3]} is a strange-looking construct. #{ ... } is the array dereference operator. It needs a reference, which is a type of scalar. But #array[ ... ] produces a list.
This is one of those situations where you need to remember the rule for list evaluation in scalar context. The rule is that there is no general rule. Each list-producing operator does its own thing. In this case, apparently the array slice operator used in scalar context returns the last element of the list. #array[1..3] in scalar context is the same as $array[3].
As you have noticed, this is not useful. Array slices aren't meant to be used in scalar context
If you want to flatten a 2-dimensional nested array structure into a 1-dimensional list, use map:
print join ' ', map { #$_ } #array[1..3]
You still use the range operator for slicing. You just need some kind of looping construct (e.g. map) to apply the array dereference operator separately to each element of the outer array.
The #{ ... } construction dereferences the scalar value of the code within the braces as an array
I'm unclear what you expect from #{ #array[1..3] }, but the list#array[1..3] in scalar context returns just the last element of the list -- $array[3] -- so you are asking for #{ $array[3] } which I guess is what you got
If you explain what you want to print then I am sure we can help, but dereferencing a list makes little sense
#array[1..3] is a list of 3 array references. You can't dereference them all at once, so you should iterate over this list and dereference each element separately:
print #$_ for #array[1..3];
print "#$_\n" for #array[1..3]; # for better looking output

Why I can use #list to call an array, but can't use %dict to call a hash in perl? [duplicate]

This question already has answers here:
Why do you need $ when accessing array and hash elements in Perl?
(9 answers)
Closed 8 years ago.
Today I start my perl journey, and now I'm exploring the data type.
My code looks like:
#list=(1,2,3,4,5);
%dict=(1,2,3,4,5);
print "$list[0]\n"; # using [ ] to wrap index
print "$dict{1}\n"; # using { } to wrap key
print "#list[2]\n";
print "%dict{2}\n";
it seems $ + var_name works for both array and hash, but # + var_name can be used to call an array, meanwhile % + var_name can't be used to call a hash.
Why?
#list[2] works because it is a slice of a list.
In Perl 5, a sigil indicates--in a non-technical sense--the context of your expression. Except from some of the non-standard behavior that slices have in a scalar context, the basic thought is that the sigil represents what you want to get out of the expression.
If you want a scalar out of a hash, it's $hash{key}.
If you want a scalar out of an array, it's $array[0]. However, Perl allows you to get slices of the aggregates. And that allows you to retrieve more than one value in a compact expression. Slices take a list of indexes. So,
#list = #hash{ qw<key1 key2> };
gives you a list of items from the hash. And,
#list2 = #list[0..3];
gives you the first four items from the array. --> For your case, #list[2] still has a "list" of indexes, it's just that list is the special case of a "list of one".
As scalar and list contexts were rather well defined, and there was no "hash context", it stayed pretty stable at $ for scalar and # for "lists" and until recently, Perl did not support addressing any variable with %. So neither %hash{#keys} nor %hash{key} had meaning. Now, however, you can dump out pairs of indexes with values by putting the % sigil on the front.
my %hash = qw<a 1 b 2>;
my #list = %hash{ qw<a b> }; # yields ( 'a', 1, 'b', 2 )
my #l2 = %list[0..2]; # yields ( 0, 'a', 1, '1', 2, 'b' )
So, I guess, if you have an older version of Perl, you can't, but if you have 5.20, you can.
But for a completist's sake, slices have a non-intuitive way that they work in a scalar context. Because the standard behavior of putting a list into a scalar context is to count the list, if a slice worked with that behavior:
( $item = #hash{ #keys } ) == scalar #keys;
Which would make the expression:
$item = #hash{ #keys };
no more valuable than:
scalar #keys;
So, Perl seems to treat it like the expression:
$s = ( $hash{$keys[0]}, $hash{$keys[1]}, ... , $hash{$keys[$#keys]} );
And when a comma-delimited list is evaluated in a scalar context, it assigns the last expression. So it really ends up that
$item = #hash{ #keys };
is no more valuable than:
$item = $hash{ $keys[-1] };
But it makes writing something like this:
$item = $hash{ source1(), source2(), #array3, $banana, ( map { "$_" } source4()};
slightly easier than writing:
$item = $hash{ [source1(), source2(), #array3, $banana, ( map { "$_" } source4()]->[-1] }
But only slightly.
Arrays are interpolated within double quotes, so you see the actual contents of the array printed.
On the other hand, %dict{1} works, but is not interpolated within double quotes. So, something like my %partial_dict = %dict{1,3} is valid and does what you expect i.e. %partial_dict will now have the value (1,2,3,4). But "%dict{1,3}" (in quotes) will still be printed as %dict{1,3}.
Perl Cookbook has some tips on printing hashes.

How do I determine the number of elements in an array reference?

Here is the situation I am facing...
$perl_scalar = decode_json( encode ('utf8',$line));
decode_json returns a reference. I am sure this is an array. How do I find the size of $perl_scalar?? As per Perl documentation, arrays are referenced using #name. Is there a workaround?
This reference consist of an array of hashes. I would like to get the number of hashes.
If I do length($perl_scalar), I get some number which does not match the number of elements in array.
That would be:
scalar(#{$perl_scalar});
You can get more information from perlreftut.
You can copy your referenced array to a normal one like this:
my #array = #{$perl_scalar};
But before that you should check whether the $perl_scalar is really referencing an array, with ref:
if (ref($perl_scalar) eq "ARRAY") {
my #array = #{$perl_scalar};
# ...
}
The length method cannot be used to calculate length of arrays. It's for getting the length of the strings.
You can also use the last index of the array to calculate the number of elements in the array.
my $length = $#{$perl_scalar} + 1;
$num_of_hashes = #{$perl_scalar};
Since you're assigning to a scalar, the dereferenced array is evaluated in a scalar context to the number of elements.
If you need to force scalar context then do as KARASZI says and use the scalar function.
You can see the entire structure with Data::Dumper:
use Data::Dumper;
print Dumper $perl_scalar;
Data::Dumper is a standard module that is installed with Perl. For a complete list of all the standard pragmatics and modules, see perldoc perlmodlib.