3

For example:

my @array = ("a","b","c");

print @array; #prints abc
print "Array is: " . @array #prints 3

What makes these two print statements different?

user3087867
  • 175
  • 1
  • 7

4 Answers4

13

Concatenation occurs in scalar context. Referring to an array in scalar context gives its length. For example:

my $x = @array;  # sets $x to the length of @array also.

If you want to expand the array's contents, you have multiple options.

If you simply want to print the array as you did in the first statement, you can change the concatenation to a comma. This will behave the most similarly to your original example, including with respect to '$,', which specifies a separator that appears after every element in the list (including the string "Array is:" and the last element of @array):

print "Array is: ", @array;

You can put it in quotes, which will interpolate it as a string, separating the elements by $". Note that $" defaults to a single space character. This can be useful if you need to concatenate it to another string:

print "Array is: " . "@array";

If you want to concatenate the array elements with no separator, or with an explicit separator other than $", you can use join. Again, this is useful in a context where you're building a string but not necessarily printing it right away.

print "Array is: " . join( "", @array );        # gives "abc"
print "Array is: " . join( " fred ", @array );  # gives "a fred b fred c"

Note: I added a link under scalar context above that goes to an excellent explanation by Mark-Jason Dominus. It's worth your time to read it. It isn't very long.

Joe Z
  • 17,413
  • 3
  • 28
  • 39
  • 1
    `print "Array is: ", @array` is more akin to OP's first example (it doesn't implicitly join on `$"`). In my opinion that's not usually the most *useful* thing, but it's worth pointing out. :) – hobbs Dec 22 '13 at 22:30
  • 1
    that will be different than `print @array` (the elements will be separated by `$"` which defaults to a space). to just print it with a string, do `print "Array is: ", @array;` (which will also add a separator, but it will be `$,`, which defaults to nothing) – ysth Dec 22 '13 at 22:31
  • @hobbs : Ok, I didn't know about `$"`, since I avoid most of the punctuation-named magic variables. I will update my answer above. – Joe Z Dec 22 '13 at 23:58
  • @ysth : Ok, I didn't know about `$,`, since I avoid most of the punctuation-named magic variables. I will update my answer above. – Joe Z Dec 22 '13 at 23:59
2

Joe Z is correct that the concatenation operator operates in scalar context, though this is not documented clearly in perldoc perlop. The full story takes a bit of explaining.

If you're unfamiliar with context in Perl, it can be very confusing because the term is overloaded. In perlop, you'll see references to things such as "string context" or "numeric context", but those special cases of scalar context and are applied after scalar context. For example, for the + operator, numeric context is assumed. For the . operator, string context is assumed. These different special cases of string or numeric context are needed but it's not always clear if a variable should be treated as a string or a number, so Perl differentiates between the two operators. Otherwise, "foo" would be treated, in "numeric" context as 0 and what does "foo"+"bar" mean? Is that foobar or 0? Thus, concatenation takes a separate operator to avoid ambiguity.

You'll see the following in perldoc perlop:

Additive Operators
   Binary "+" returns the sum of two numbers.
   Binary "-" returns the difference of two numbers.
   Binary "." concatenates two strings.

And this in perldoc glossary:

scalar context
   The situation in which an expression is expected by its
   surroundings (the code calling it) to return a single value rather
   than a list of values. See also context and list context. A scalar
   context sometimes imposes additional constraints on the return
   value. See string context and numeric context.

For your case, since the dot operator uses "string context", we first get a conversion to the scalar value and the scalar value of a three-element array is 3. That number is then interpreted in "string" context, resulting in the confusing behavior you found.

Context, unfortunately, is one of the things that trips up new Perl developers the most, but once you get used to it, it's very natural and can save a lot of typing (no pun intended).

As a further example to help you understand, the following prints 6:

$ perl -E '@a = qw(a b);@b = qw(c d e f); say @a + @b'

@a and @b are each evaluated in scalar context and those return 2 and 4 respectively and those are added in numeric context. If you swapped the + operator for a ., you'd see 24 printed.

Ovid
  • 11,580
  • 9
  • 46
  • 76
1

The 1st operation performed in the last line is concatenation to a scalar value "Array is: ". In order to do that Perl needs to convert the 2nd operand @array into a scalar type as well. The convention in Perl for array to scalar conversion is not concatenation of all array's element, but the number of elements, so that you could also print something like 5 + @array. Therefore the expression prints "Array is : 5".

The 1st print statement doesn't have to perform array to scalar conversion, therefore it prints the array contents.

Michael
  • 5,775
  • 2
  • 34
  • 53
0

Because @array in scalar Context .

print "Array is : @array";
Chinaxing
  • 8,054
  • 4
  • 28
  • 36