my @a = (1,2,3,4,5);
print @a; #output: 12345
print \"\\n\";
print \"@a\"; #output: 1 2 3 4 5
Printing an array by putting its name with
When Perl sees an array in an interpolated string, it rewrites it using join:
print "@array";
becomes
print join($" => @array);
by default, the value of $"
is equal to a single space.
You can configure this behavior by localizing a change to $"
print "@array"; # '1 2 3 4 5'
{
local $" = ''; # "
print "@array"; # '12345'
}
print "@array"; # '1 2 3 4 5'
You can see how Perl rewrites your interpolated strings using the -q
option of the core B::Deparse
module:
$ perl -MO=Deparse,-q -e 'print "@array"'
print join($", @array);
-e syntax OK
The “Array Interpolation” section of the perldata documentation explains how the intercalated spaces in the value of "@a"
get there:
Arrays and slices are interpolated into double-quoted strings by joining the elements with the delimiter specified in the
$"
variable ($LIST_SEPARATOR
ifuse English;
is specified), space by default. The following are equivalent:$temp = join($", @ARGV); # " for benefit of StackOverflow hiliter system "echo $temp"; system "echo @ARGV";
This means that print "@a"
passes a single scalar argument to print
. In contrast, print @a
in your example passes five.
The perlfunc documentation on print explains what print
with a list of arguments.
print LIST
… The current value of
$,
(if any) is printed between each LIST item.
The perlvar documentation on $, is
Handle->output_field_separator( EXPR )
$OUTPUT_FIELD_SEPARATOR
$OFS
$,
The output field separator for the print operator. If defined, this value is printed between each of print's arguments. Default is
undef
.Mnemonic: what is printed when there is a
,
in your
Because $,
defaults to the undefined value, you're seeing print
output its arguments with no separator. In explicit terms, the code from your question is equivalent to
print join("", @a);
The difference in behavior isn't a special case for print
. Arrays interpolate into all double-quoted strings as described above. A quick survey of Google code-search hits for print "@... seems to indicate that a frequent use for print "@foo"
is debugging output, as in
sub foo {
print "args = @_\n" if $debug;
...;
}
A handy trick that Mark Dominus uses to provide visible separators for lists whose values may contain spaces is
sub foo {
if ($debug) {
local $" = "][";
print "args = [@_]; # e.g., [foo][1][3.14159]
}
...;
}
Say @a
contains lines of output such as
@a = map " - $_\n", @error_messages;
print @a;
Inserting implicit spaces between the values would hose my carefully constructed formatting:
- sneaky-sneaky, sir - the hideousness of that foot will haunt my dreams forever - why would you do that?!
Perl tries hard to do what we mean, even when we're inconsistent in the demands we make.
Even better question: Why doesn't it print something like array{0x1232ef}. Print is suppose to print a string output and @a
isn't a scalar.
Heck, even better: This is a scalar context, so why not print 5
which is the number of elements in the array. This is how:
print scalar @a;
would print.
Instead, the print
command is taking some liberties to try to do what you intended and not what you said you want.
Let's take a look at this little program:
@a = qw(a b c d e);
print "@a"; #prints "a b c d e"
print "\n";
print @a; #prints "abcde"
print "\n";
print @a . "\n"; #prints "5"
print scalar @a; #prints "5"
Notice that print @a
prints abcde
, but if I add a \n
on the end, it then prints @a
in a scalar context.
Take a look at the Perldoc on print (try the command perldoc -f print
. On most systems, the entire Perl documentation is available via perldoc
)
* print LIST
* print
Prints a string or a list of strings. Returns true if successful[...]
Ah! If given a list, it'll print a list of strings.
The current value of $, (if any) is printed between each LIST item. The current value of $\ (if any) is printed after the entire LIST has been printed. Because print takes a LIST, anything in the LIST is evaluated in list context, including any subroutines whose return lists you pass to print.
Let's try a new program:
@a = qw(a b c d e);
$, = "--";
print "@a"; #prints "a b c d e"
print "\n";
print @a; #prints "a--b--c--d--e"
print "\n";
print @a . "\n"; #prints "5"
print scalar @a; #prints "5"
Hmmm... The $,
added the double dashes between the list elements, but it didn't affect the @a
in quotes. And, if $,
is mentioned in the perldoc
, why is everyone prattling about $"
?
Let's take a look at perldoc perlvar
* $LIST_SEPARATOR
* $"
When an array or an array slice is interpolated into a double-quoted string or a
similar context such as /.../ , its elements are separated by this value. Default
is a space. For example, this:
print "The array is: @array\n";
is equivalent to this:
print "The array is: " . join($", @array) . "\n";
Mnemonic: works in double-quoted context.
So, that explains everything!
The default of $"
is a single space, and the default of $,
is null. That's why we got what we got!
One more program...
@a = qw(a b c d e);
$, = "--";
$" = "++";
print "@a"; #prints "a++b++c++d++e"
print "\n";
print @a; #prints "a--b--c--d--e"
print "\n";
print @a . "\n"; #prints "5"
print scalar @a; #prints "5"
When an array is interpolated in a string, the assumption is you may want to be able to visually distinguish elements; when you print a list, the assumption is you just want that data output contiguously. Both are configurable; $, (default '') is inserted between elements of a list being printed, while $" (default ' ') is inserted between elements of an array interpolated into a string.
In the first instance, you are passing a list of arguments to print
, and each is printed in turn.
In the second, you are interpolating an array into a string, and then printing the result.
When an array in interpolated in a string, the values are separated by $"
, which defaults to .