Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question on printing an array

2 views
Skip to first unread message

sc_wi...@hotmail.com

unread,
May 23, 2006, 1:42:38 PM5/23/06
to
Hi everyone,

This is a basic beginner's questions concerning the 'print' function :

my @array = 1..3;
print @array , "\n"; # prints : 123
print @array . "\n," # prints : 3 (the array size)

I was surprised to see that the second 'print' call prints the array
size... my guess is that at one particular moment, @array is evaluated
in a scalar context which gives the array size, but I don't see exactly
where and why this evaluation is done.

Can someone give me a few hints on this ?

Thanks for helping...

Mothra

unread,
May 23, 2006, 2:04:14 PM5/23/06
to
sc_wi...@hotmail.com wrote:
> Hi everyone,
>
> This is a basic beginner's questions concerning the 'print' function :
>
> my @array = 1..3;
> print @array , "\n"; # prints : 123
> print @array . "\n," # prints : 3 (the array size)
>
use strict;
use warnings;
my @array = (1..5);

print map{$_ , "\n"} @array;

hope this helps

Mothra


l v

unread,
May 23, 2006, 2:42:03 PM5/23/06
to

The second print is doing string concatenation (the period) which causes
print() to print in scalar mode. Adding scalar to the first print()
will also cause print() to print in scalar mode.

my @array = 1..3;
print scalar @array , "\n"; # prints : 123


print @array . "\n," # prints : 3 (the array size)

__output__
3
3

--

Len

use...@davidfilmer.com

unread,
May 23, 2006, 3:18:05 PM5/23/06
to
Mothra wrote:

> print map{$_ , "\n"} @array;

Many would prefer:

print "$_\n" for @array;

--
http://DavidFilmer.com

sc_wi...@hotmail.com

unread,
May 23, 2006, 3:33:59 PM5/23/06
to
Len, thanks for your answer... this new "scalar or list context" theory
sometimes gives me headaches ;)

Dr.Ruud

unread,
May 23, 2006, 3:58:33 PM5/23/06
to
use...@DavidFilmer.com schreef:
> Mothra wrote:

>> print map{$_ , "\n"} @array;
>
> Many would prefer:
>
> print "$_\n" for @array;

More (but certainly not better) alternatives:

local $\ = "\n";
print for @array;


use Perl6::Say ;
say for @array ;


local $" = "\n" ;
print "@array\n" ;

etc.

--
Affijn, Ruud

"Gewoon is een tijger."


Jim Gibson

unread,
May 23, 2006, 5:17:44 PM5/23/06
to
In article <1148412839....@i40g2000cwc.googlegroups.com>,
<sc_wi...@hotmail.com> wrote:

> Len, thanks for your answer... this new "scalar or list context" theory
> sometimes gives me headaches ;)
>

Welcome to the club! It gives a lot of people headaches. If you think
that is bad, wait until you encounter the list vs. array dichotomy.

See perldoc -q list
"What is the difference between a list and an array?"

Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com

Uri Guttman

unread,
May 23, 2006, 6:45:10 PM5/23/06
to l v
>>>>> "lv" == l v <veat...@yahoo.com> writes:

lv> The second print is doing string concatenation (the period) which
lv> causes print() to print in scalar mode. Adding scalar to the
lv> first print() will also cause print() to print in scalar mode.

that has nothing to do with print and you keep saying print in scalar
mode. it is much simpler that all that. . (concatenate) provides scalar
(and string) context to both of its arguments. an array will return its
size (in this case 3), have that converted to a string, concatenate that
with "\n" and that string is passed to print. print provides only list
context to its args but will convert them all to strings internally for
printing.

uri

--
Uri Guttman ------ u...@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Uri Guttman

unread,
May 23, 2006, 6:47:18 PM5/23/06
to
>>>>> "u" == usenet <use...@DavidFilmer.com> writes:

u> Mothra wrote:
>> print map{$_ , "\n"} @array;

u> Many would prefer:

u> print "$_\n" for @array;

i am not one of those. my rule is print rarely, print late. your code
calls print for each element and print is slow as it invokes PerlIO or
stdio each time. the map version calls print only once. and that is
better written as:

print map "$_\n", @array;

John W. Krahn

unread,
May 23, 2006, 7:26:03 PM5/23/06
to
l v wrote:

> sc_wi...@hotmail.com wrote:
>>
>> This is a basic beginner's questions concerning the 'print' function :
>>
>> my @array = 1..3;
>> print @array , "\n"; # prints : 123
>> print @array . "\n," # prints : 3 (the array size)
>>
>> I was surprised to see that the second 'print' call prints the array
>> size... my guess is that at one particular moment, @array is evaluated
>> in a scalar context which gives the array size, but I don't see exactly
>> where and why this evaluation is done.
>
> The second print is doing string concatenation (the period) which causes
> print() to print in scalar mode. Adding scalar to the first print()
> will also cause print() to print in scalar mode.

print() does not have a "scalar mode". All of the arguments (except the
filehandle) to print are in list context. It is the concatenation operator
that sets its operands to scalar context and scalar() is a unary operator so
it only affects the expression immediately following it in a list.


John
--
use Perl;
program
fulfillment

Charles DeRykus

unread,
May 23, 2006, 8:53:57 PM5/23/06
to
Uri Guttman wrote:
>>>>>> "u" == usenet <use...@DavidFilmer.com> writes:
>
> u> Mothra wrote:
> >> print map{$_ , "\n"} @array;
>
> u> Many would prefer:
>
> u> print "$_\n" for @array;
>
> i am not one of those. my rule is print rarely, print late. your code
> calls print for each element and print is slow as it invokes PerlIO or
> stdio each time. the map version calls print only once. and that is
> better written as:
>
> print map "$_\n", @array;
>

That's certainly shorter and clearer which trumps any speed
consideration IMO.

It might be worth noting though that interpolation could cause
the map EXPR format to be a few bejillioniths of a sec slower...
I'd benchmark but it's time for my nap...


--
Charles DeRykus

MSG

unread,
May 23, 2006, 9:51:59 PM5/23/06
to
Uri Guttman wrote:
> print map "$_\n", @array;

I am surprised that nobody even mentioned 'join'!
print join "\n", @array;

Jürgen Exner

unread,
May 23, 2006, 10:34:05 PM5/23/06
to

Simple.
In the first case @array is an argument for print() ==> print expects list
context
In the second case @array is an argument for . ==> . expects two scalars

jue


Charles DeRykus

unread,
May 23, 2006, 10:52:04 PM5/23/06
to

You'd need to make that: join("\n,@array), "\n"

--
Charles DeRykus

John Bokma

unread,
May 23, 2006, 11:44:00 PM5/23/06
to
Charles DeRykus <c...@blv-sam-01.ca.boeing.com> wrote:

Why? that gives an error :-)

print join "\n", @array, "";

or

print join "\n", @array, '';


works though, if you want also a final \n; since an empty element is added
to the list.

--
John Bokma Freelance software developer
&
Experienced Perl programmer: http://castleamber.com/

Ala Qumsieh

unread,
May 24, 2006, 12:49:28 AM5/24/06
to
Charles DeRykus wrote:
> Uri Guttman wrote:
>
>>>>>>> "u" == usenet <use...@DavidFilmer.com> writes:

>> u> print "$_\n" for @array;
>>

>> print map "$_\n", @array;
>>
>
> That's certainly shorter and clearer which trumps any speed
> consideration IMO.

To be pedantic, that is neither shorter, nor clearer. David's solution
is one character shorter, and is certainly clearer than the map()
solution in the way it conveys the coder's intentions. But, I agree with
Uri in that print() should be called as few times as possible, although
I don't see that as a big issue in short-running programs.

> It might be worth noting though that interpolation could cause
> the map EXPR format to be a few bejillioniths of a sec slower...
> I'd benchmark but it's time for my nap...

Not sure what you mean there. Both interpolate.
--Ala

Tad McClellan

unread,
May 24, 2006, 1:51:58 AM5/24/06
to
sc_wi...@hotmail.com <sc_wi...@hotmail.com> wrote:

> this new "scalar or list context" theory
> sometimes gives me headaches ;)


It shouldn't.

You do this very same thing everyday without much trouble!

Give me a fish

Give me several fish

The word "fish" has two different meanings.

In one usage "fish" is a singular noun, and in the other it is
a plural noun.

How can we tell that?

From looking at "what is around" the word fish.

What is another word for "what is around"? .... context!


List vs. scalar context is not new nor scary.

What might be new is seeing it in a programming language rather
than in a natural language.


--
Tad McClellan SGML consulting
ta...@augustmail.com Perl programming
Fort Worth, Texas

Anno Siegel

unread,
May 24, 2006, 6:49:42 AM5/24/06
to
Charles DeRykus <c...@blv-sam-01.ca.boeing.com> wrote in comp.lang.perl.misc:

ITYM

print join( "\n", @array), "\n";

Shorter:

print join "\n", @array, '';

Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Charles DeRykus

unread,
May 24, 2006, 12:38:37 PM5/24/06
to

No, you clipped too much. I believe Uri was correcting Mothra's
`map` suggestion at that juncture rather than David's `for` loop
(also criticized). And I believe that Mothra's map, although not
as short and arguably a bit less clear than Uri's, will be faster.

Mothra> print map{$_ , "\n"} @array;
...
David> print "$_\n" for @array;

Uri> i am not one of those. my rule is print rarely, print late.
Uri> your code calls print for each element and print is slow
Uri> as it invokes PerlIO or
Uri> stdio each time. the map version calls print only once. and
Uri> that is better written as:
Uri. print map "$_\n", @array;

--
Charles DeRykus

Uri Guttman

unread,
May 24, 2006, 1:16:36 PM5/24/06
to
>>>>> "CD" == Charles DeRykus <c...@blv-sam-01.ca.boeing.com> writes:

Mothra> print map{$_ , "\n"} @array;

CD> Uri. print map "$_\n", @array;

CD> No, you clipped too much. I believe Uri was correcting Mothra's
CD> `map` suggestion at that juncture rather than David's `for` loop
CD> (also criticized). And I believe that Mothra's map, although not
CD> as short and arguably a bit less clear than Uri's, will be faster.

mothra's will pass to print a list of the lines and newlines so print
will have to loop over each element and then call into its internals
which are slow. my version generates half as many values and passes
those to print so it should be faster. the join idea should even be
faster than that since it passes only 1 string to print. these are easy
enough for someone to benchmark.

and the second part of my rule (print late) comes into play here, print
late. i write most subs which do 'printing' to actually build strings
(typically with .= which is fast) and return them. only the highest
level sub actually will do the print as it can decide to choose where to
print, print multiple places, send the text over a pipe, encapsulate the
text, escape it all, convert it, etc. if each lower sub had to choose
what to do, it makes for a mess. this includes solutions like passing in
a filehandle to print to. why pass in an extra arg all over? what if you
want to change the code to print and also log the text? do you pass in a
tied handle to do that? best to just return text until you pop up to the
sub that can make the decisions and do the required i/o.

so remember to print rarely, print late.

Dr.Ruud

unread,
May 24, 2006, 6:50:37 PM5/24/06
to
Uri Guttman schreef:
> usenet:
>> Mothra:

>>> print map{$_ , "\n"} @array;
>>

>> Many would prefer:


>>
>> print "$_\n" for @array;
>
> i am not one of those. my rule is print rarely, print late. your code
> calls print for each element and print is slow as it invokes PerlIO or
> stdio each time. the map version calls print only once. and that is
> better written as:
>
> print map "$_\n", @array;

I assume that

{ local ($,, $\) = ("\n", "\n") ; print @array }

tops that, especially for large arrays.

Uri Guttman

unread,
May 24, 2006, 7:09:20 PM5/24/06
to
>>>>> "R" == Ruud <rvtol...@isolution.nl> writes:

R> Uri Guttman schreef:
>> usenet:
>>> Mothra:

>>>> print map{$_ , "\n"} @array;
>>>
>>> Many would prefer:
>>>
>>> print "$_\n" for @array;
>>
>> i am not one of those. my rule is print rarely, print late. your code
>> calls print for each element and print is slow as it invokes PerlIO or
>> stdio each time. the map version calls print only once. and that is
>> better written as:
>>
>> print map "$_\n", @array;

R> I assume that

R> { local ($,, $\) = ("\n", "\n") ; print @array }

R> tops that, especially for large arrays.

i would doubt it. map or join is optimized for this but print is so
general purpose that who knows what it does with $, and $\ internally. i
would stick with building your own larger strings and calling print as
rarely as possible. this is of course where you need this speed and not
for short scripts where you can just print as needed.

Dr.Ruud

unread,
May 24, 2006, 9:32:07 PM5/24/06
to
Uri Guttman schreef:
> Ruud:
>> Uri:

>>> print map "$_\n", @array;
>>

>> I assume that


>> { local ($,, $\) = ("\n", "\n") ; print @array }

>> tops that, especially for large arrays.
>
> i would doubt it. map or join is optimized for this but print is so
> general purpose that who knows what it does with $, and $\
> internally.

I just tested it with an array with millions of elements, and the
map-version was about 3 times slower than three other methods (that each
took about one minute).


#!/usr/bin/perl
use strict ;
use warnings ;

my $N = 2_000_000 ;

my $M = @ARGV ? $ARGV[0] : 0 ;
# 1: $\ = $, = "\n"; print @_
# 2: print map "$_\n", @_
# 3: print "$_\n" for @_
# 4: $\ = "\n"; print for @_

print "M:$M\n" ;
print "N:$N\n" ;

$_[$N-1] = $N ; # preallocation?
for my $i ( 1 .. $N ) {
$_[$i-1] = $i ;
}

if (1 == $M)
{


local ($,, $\) = ("\n", "\n") ;

print @_ ;
}
elsif (2 == $M)
{
print map "$_\n", @_ ;
}
elsif (3 == $M)
{
print "$_\n" for @_ ;
}
elsif (4 == $M)
{
local $\ = "\n" ;
print for @_ ;
}
else
{
print "#:$_[-1]\n" ;
}
__END__

0 new messages