tags:

views:

144

answers:

5

I am new to Perl. I wrote a snippet to access array elements and print it to the console:

use strict;
use warnings;

my @array1 = ('20020701  00000', 'Sending Mail in Perl', 'Philip Yuson');
my @array2 = ('20020601', 'Manipulating Dates in Perl', 'Philip Yuson');
my @array3 = ('20020501', 'GUI Application for CVS', 'Philip Yuson');
my @main = (\@array1, \@array2, \@array3);

my $a = $main[0];
print @$a;
print @$a . "pdf";

First print:

20020701  00000Sending Mail in PerlPhilip Yuson

But why second print outputs this?

3pdf 

I need to get the output like

20020701  00000Sending Mail in PerlPhilip Yusonpdf

I don't know why it is giving 3pdf i am pressed get out of this. Any Help is greatly appreciated.

+14  A: 

Arrays are one of the parts of Perl that act differently according to the “context”, which is a very important concept in Perl programming. Consider this:

my @fruits = qw/apples pears bananas/;
my $items = @fruits;

On the second line you are assigning to a scalar (⇒ here we have some context), but on the right side you have an array. We say that the array here is used in scalar context, and in scalar context the value of an array is the number of its items.

Now to your problem: When you are simply printing the array, there is not much magic involved. But when you try to append a string onto the array using the . operator, you are using the array in scalar context. Which means the array evaluates to the number of its items (3), to which you append the pdf.

Is that clear? You should Google up something on “Perl context”, that will make Perl programming much easier for you.

zoul
+7  A: 

This is a matter of contexts. In Perl, the data type of a value is only part of what evaluates to; the other half is the context that value is used in.

As you may know, there are three built-in data types: scalars, arrays, and hashes. There is also some degree of implicit casting that can be done between these data types.

There are also two major contexts: list and scalar. Arrays and hashes both work without casting in list context; scalar values work without change in scalar contexts.

The behavior of an operator can depend on the context it is run in. If an operator requires a particular context, and Perl is able to implicitly cast the value into something matching that context, it will. In the case of arrays and associative arrays being cast to integers, what you get is the ''cardinality'' of the array, the number of elements it contains.

In your example above, @$a evaluates to data typed as an array. The other half of that story, though, is the context in which the operator . runs in. Reading perldoc perlop, it says the following:

Binary . concatenates two strings.

Well, strings are scalar values, and so we need to cast the array @$a to be valid in a scalar context, and in doing so get the back the cardinality of the array. @$a contains 3 things, so this evaluates to the scalar value 3, which is then turned into a string so the . operator can work its magic.

Hope this makes some sense.

Ed Carrel
There's no such thing as "hash context" - or array context for that matter (despite the misnamed `wantarray` function). There's scalar context and list context, and a few minor wiggles like boolean context (a subset of scalar)
friedo
You have some errors. Contexts are `void`, `list` and `scalar`. `Boolean`, `string` and `numeric` contexts are types of scalar context. Also, hashes in scalar context return the number of used and allocated buckets--not the number of members, see perldata for more info. Also, when you mention "array context" it makes me think you are conflating lists and arrays, there is a big difference: http://perldoc.perl.org/perlfaq4.html#What-is-the-difference-between-a-list-and-an-array%3f
daotoad
You are both right. I've edited my answer to hopefully get rid of some of the inaccuracies.
Ed Carrel
+5  A: 

print @$a . "pdf" evaluates the array in scalar context, this outputting the number of elements in the array, which is why you get 3.

You're probably looking for something like this:

print @$a, "pdf";

The comma operator instead of dot forces it into list context.

Rohan Almeida
+14  A: 

The 3 is the number of elements in the array. The . is forcing the array into scalar context, and then you get the number of elements instead of the array contents. You could use

print "@$a pdf";

or

print @$a , "pdf";

depending on what kind of output you want.

Kinopiko
+3  A: 

I have a feeling what you really would like is:

print "@$a.pdf", "\n";

That is:

my @array1 = ('20020701  00000', 'Sending Mail in Perl', 'Philip Yuson');
my @array2 = ('20020601', 'Manipulating Dates in Perl', 'Philip Yuson');
my @array3 = ('20020501', 'GUI Application for CVS', 'Philip Yuson');
my @main = (\@array1, \@array2, \@array3);

for my $x ( @main ) {
    print "@$x.pdf", "\n";
}

Output:

20020701  00000 Sending Mail in Perl Philip Yuson.pdf
20020601 Manipulating Dates in Perl Philip Yuson.pdf
20020501 GUI Application for CVS Philip Yuson.pdf
Sinan Ünür