Question on printing an array

S

sc_wizard29

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...
 
M

Mothra

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

l v

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...

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
 
S

sc_wizard29

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

Dr.Ruud

(e-mail address removed) schreef:
Mothra wrote:

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.
 
U

Uri Guttman

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
 
U

Uri Guttman

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;

uri
 
J

John W. Krahn

l said:
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
 
C

Charles DeRykus

Uri said:
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...
 
J

Jürgen Exner

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 ?

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
 
J

John Bokma

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

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.
 
A

Ala Qumsieh

Charles said:
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
 
T

Tad McClellan

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.
 
C

Charles DeRykus

Ala said:
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.


Not sure what you mean there. Both interpolate.

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;
 
U

Uri Guttman

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.

uri
 
D

Dr.Ruud

Uri Guttman schreef:
usenet:

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,742
Latest member
AshliMayer

Latest Threads

Top