array

J

J. Gleixner

What's wrong in this code?

use strict;
use warnings;

my @cats=["striper","snowball"]; ^( ^)

print $cats[0];
print $cats[1];


[] creates a reference to an anonymous array reference.
() creates a list.

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

To store a list as an array:

my @cats = ( 'striper', 'snowball' );
print $cats[0];
push( @cats, 'tiger' )

To use an anonymous array reference, you have to dereference the variable.

my $cats = [ 'striper', 'snowball' ];
print $cats->[0];
push( @$cats, 'tiger' )

Learning how to use references is very important in many languages.
After you learn about arrays and hashes, then take a look at references.

See: perldoc perlreftut



You can also take a look at using qw() to help clean up things when you
create a list. e.g.

my @cats = qw( striper snowball );
 
B

Bill Cunningham

What's wrong in this code?

use strict;
use warnings;

my @cats=["striper","snowball"];

print $cats[0];
print $cats[1];

Bill
 
B

Bill Cunningham

Eli said:
In comp.lang.perl.misc said:
What's wrong in this code?

use strict;
use warnings;

my @cats=["striper","snowball"];
^ ^

You probably want parens there:

my @cats=("striper","snowball");

Oh. OK left over from C where arrays are in []. Gotta learn something
new.
What you have is an array presented as a single value.
print $cats[0];
print $cats[1];

With your code, striper and snowball are in:

print $cats[0][0];
print $cats[0][1];

Goodness when I see this I think char **. I have to change my thinking
here. There are no pointers in perl are there?
 
B

Bill Cunningham

Henry said:
Oh yes ... but don't you dare call them that! All sorts of contumely
will be your portion. :)

Look up "references". "perldoc perlreftut" on a command line will get
you started, or you may have some other way of getting at the built-in
documentation.

I have to use man perlintro on my linux. I'm not even through reading
it. I must've forgot how to use lists.
 
J

Jürgen Exner

Bill Cunningham said:
Goodness when I see this I think char **. I have to change my thinking
here. There are no pointers in perl are there?

There are many in perl, but none in Perl.

perl is the interpreter and of course its implementation uses plenty of
pointers.
However the programming language Perl uses references to create dynamic
data structures, which are _MUCH_ more programmer-friendly than
primitive pointers.

jue
 
P

Peter J. Holzer

Eli said:
In comp.lang.perl.misc said:
What's wrong in this code? [...]
my @cats=["striper","snowball"];
^ ^

You probably want parens there:

my @cats=("striper","snowball");

Oh. OK left over from C where arrays are in [].

No. Initializers in C are in {}:

int a[] = {1, 2, 3};

This would be a syntax error:

int a[] = [1, 2, 3];

Lists are denoted by [] in Python.

hp
 
P

Peter J. Holzer

There are many in perl, but none in Perl.

perl is the interpreter and of course its implementation uses plenty of
pointers.
However the programming language Perl uses references to create dynamic
data structures,

There is no universally agreed upon definition of the terms "reference"
and "pointer" which allows to distinguish between these two terms.

A "pointer" in Pascal has different properties than a "pointer" in C or
C++. C++ distinguishes between "references" and "pointers". Java
doesn't have anything called "pointers" or "references", but clearly
object variables" don't contain an object, they "reference" it or "point
to" it. Other languages have different convention.

In Perl, the term is "reference", but as for all other languages, this
is language-specific jargon, not a conceptional difference.

A Perl "reference" is very similar to a Pascal "pointer" or a Java
"object variable". It is quite different from both a C++ "pointer" and a
C++ "reference", although it is closer to the "pointer" than the
"reference" (A C++ "reference" is similar to a Perl "alias").

So yes, there are "pointers" in the generic sense in Perl and they are
called "references". There is no equivalent to "C or C++ pointers" in
Perl.
which are _MUCH_ more programmer-friendly than primitive pointers.

I would argue that a C pointer is *less* primitive than a Perl
reference. A perl reference can only be dereferenced, assigned, and
compared for equality. A C pointer has a much richer set on operations
defined on it: In addition to the operations possible on a Perl
reference (or a Pascal pointer), you can add or subtract an integer, you
can subtract one pointer from another and you can order them.

C doesn't do garbage collection, but that's a property of the language
as a whole, not of C-type pointers. A language with C-type pointers and
garbage collection is entirely possible. (Indeed, I think the C standard
even allows this, but it doesn't mandate it).

hp
 
K

Keith Thompson

Bill Cunningham said:
Eli said:
In comp.lang.perl.misc said:
What's wrong in this code?

use strict;
use warnings;

my @cats=["striper","snowball"];
^ ^

You probably want parens there:

my @cats=("striper","snowball");

Oh. OK left over from C where arrays are in []. Gotta learn something
new.

Perl does use [] for array accesses.

Don't base your attempt to learn Perl on your knowledge of C.
It's a very different language (with some similar syntax) with a
very different memory model.
 
R

Rainer Weikusat

Bill Cunningham said:
Eli said:
In comp.lang.perl.misc said:
What's wrong in this code?

use strict;
use warnings;

my @cats=["striper","snowball"];
^ ^

You probably want parens there:

my @cats=("striper","snowball");

Oh. OK left over from C where arrays are in []. Gotta learn something
new.

The difference is that (1, 2, 3) in list context is a so-called list
value constructor this means it evaluates to a list of the values in
brackets. That's what you have to use when you want to initialize an
array:

my @a = ('striper', 'snowball')

Assigning a list of values to an array has the obvious semantics. In
contrast to this, [1, 2, 3] creates a reference to an anonymous array
holding the values inside the brackets. Assigning that to an array, as
in

my @a = [1, 2, 3];

assigns this reference to an anonymous array to $a[0].

[...]
With your code, striper and snowball are in:

print $cats[0][0];
print $cats[0][1];

Goodness when I see this I think char **. I have to change my thinking
here. There are no pointers in perl are there?

There are 'references' which perform a similar function for perl. The
perlref and perlrefut, perldsc and perllol manapage explain most of
the non-OO-relevant details[*].

[*] Since the people who presently control perl consider it
sexy to remove technically correct documentation for political
reasons, you might or might not have them.
 
B

Bill Cunningham

Keith said:
Perl does use [] for array accesses.

Don't base your attempt to learn Perl on your knowledge of C.
It's a very different language (with some similar syntax) with a
very different memory model.

Higher level too. Much easier to use. Here I don't think arrays have to
be iterated over like with C. I can't even remember right off how to do
that. Checking out perl is going to be an experience.

Bill
 
D

Dr.Ruud

Bill:

There's a for statement with C-like syntax, but I don't believe that
I've ever used it; I find foreach more convenient. If you're iterating
over steps rather than over elements of an array, you can still use
foreach, in conjunction with a range operator:

foreach (1..10)

In Perl, 'for' and 'foreach' are the same.


Be careful with long ranges
like for ( 1 .. 1_000_000_000 ),
since they are not lazy:

time perl -wle '
my $i;
for ( 1 .. 100_000_000 ) {
++$i;
}
print $i;
'
100000000

real 0m10.005s
user 0m9.966s
sys 0m0.016s


time perl -wle '
my $i;
foreach ( $i= 0; $i < 100_000_000; $i++ ) {
++$i;
}
print $i;
'
100000000

real 0m6.321s
user 0m6.291s
sys 0m0.012s
 
P

Peter J. Holzer

Keith said:
Perl does use [] for array accesses.

Don't base your attempt to learn Perl on your knowledge of C.
It's a very different language (with some similar syntax) with a
very different memory model.

Higher level too. Much easier to use. Here I don't think arrays have to
be iterated over like with C.

If you want to do something with every element of an array you have to
iterate over it. This is completely independent of the language. Perl
just gives you more ways to do it than C, some of them hide the
mechanics of iterating:


In C, given an array a with n members:

for (int i = 0; i < n; i++) {
do something with a
}

In Perl, C-like loop:

for (my $i = 0; $i <= $#a; $i++) {
do something with $a[$i];
}

(note that you don't have to know n here - you can get the last valid
index from the array itself)

In Perl, "foreach" loop (the name is a bit misleading):

for my $e (@a) {
do something with $e
}

(note that this doesn't use an index at all, $e is aliased to all
elements in order).

And since perl 5.14, you can get the index and the element in parallel:

while (my ($i, $e) = each @a) {
do something with $i and/or $e
}

And finally, often you want to transform each element of an array and
assign the resulting list to a new array:

my @b = map { do something with $_ } @a;


Plus there are a lot more functions (both builtin and in modules) which
operate on whole arrays, so you will be writing less explicit loops in
Perl than in C.

And another one (I am starting to feel like a standup comedian): In
Perl, strings are first-class citizens, not arrays of bytes, so that
eliminates another reason for explicit loops.

And finally, there are hashes.

And now I'm finishing this article, before I think of something else
which might be implemented by explicitely iterating over an array in C
but which is done differently in Perl.

hp
 
P

Peter J. Holzer

In Perl, 'for' and 'foreach' are the same.

Yes. But this style of loop is still commonly called the "foreach loop",
even though almost everybody writes “for (1..10)â€.

Be careful with long ranges
like for ( 1 .. 1_000_000_000 ),
since they are not lazy:

Yes, they are. See below.

time perl -wle '
my $i;
for ( 1 .. 100_000_000 ) {
++$i;
}
print $i;
'
100000000

real 0m10.005s
user 0m9.966s
sys 0m0.016s


time perl -wle '
my $i;
foreach ( $i= 0; $i < 100_000_000; $i++ ) {
++$i;
}
print $i;
'
100000000

real 0m6.321s
user 0m6.291s
sys 0m0.012s

This increments $i twice per iteration, so the loop runs only 50 million
times. Do it right and it is slower than the “foreach loopâ€:

time perl -wle '
my $j;
foreach ( $i= 0; $i < 100_000_000; $i++ ) {
++$j;
}
print $j;
'

13.63s vs. 9.10s on one system,
7.43s vs. 5.47s on another.

Just for laughs, here is the non-lazy version:

time perl -wle '
my $i;
my @a = ( 1 .. 100_000_000 );
for (@a) {
++$i;
}
print $i;
'
100000000
perl -wle 22.57s user 23.30s system 99% cpu 45.938 total

So this is about 45.94 / 5.47 == 8.4 times slower than the foreach loop
with the range operator and it uses about 7.5 GB of virtual memory (so
it doesn't even run on a 32 bit system).

hp
 
D

Dr.Ruud

Yes. But this style of loop is still commonly called the "foreach loop",
even though almost everybody writes “for (1..10)â€.

Yes, they are. See below.



This increments $i twice per iteration, so the loop runs only 50 million
times. Do it right and it is slower than the “foreach loopâ€:

time perl -wle '
my $j;
foreach ( $i= 0; $i < 100_000_000; $i++ ) {
++$j;
}
print $j;
'

13.63s vs. 9.10s on one system,
7.43s vs. 5.47s on another.

Just for laughs, here is the non-lazy version:

time perl -wle '
my $i;
my @a = ( 1 .. 100_000_000 );
for (@a) {
++$i;
}
print $i;
'
100000000
perl -wle 22.57s user 23.30s system 99% cpu 45.938 total

So this is about 45.94 / 5.47 == 8.4 times slower than the foreach loop
with the range operator and it uses about 7.5 GB of virtual memory (so
it doesn't even run on a 32 bit system).


Ah, thanks for the correction, and sorry for spreading FUD.
I had been bitten by this once,
but that must then have been that array version.
 
P

Peter J. Holzer

Yes, they are. See below.
[big snip]
Ah, thanks for the correction, and sorry for spreading FUD.
I had been bitten by this once,
but that must then have been that array version.

for (1 .. $n) { ... } did indeed build a temporary list once upon time.
That was long ago (I don't remember when it was changed. 5.6?), but as a
long-time perl programmer it is quite likely that were bitten by this.

One of the reasons why I hang out in this newsgroup is that the
discussions here constantly cause me to test the validity of my old
prejudices by re-running old benchmarks or to writing new ones.

hp
 
D

Dr.Ruud

In <[email protected]>, on 11/03/2012
at 12:23 PM, "Dr.Ruud" <[email protected]> said:

"for loops" in perlsyn documents the C-style for loop as distint from
foreach..

From perlsyn:

The "foreach" keyword is actually a synonym for the "for" keyword, so
you can use "foreach" for readability or "for" for brevity.

(I just never use foreach)
 
P

Peter J. Holzer

From perlsyn:

The "foreach" keyword is actually a synonym for the "for" keyword, so
you can use "foreach" for readability or "for" for brevity.

I very much suspect that Shmuel knows this.

But the documentation still calls this style of loops "Foreach Loops"
and the C-style loops "For loops".
(I just never use foreach)

Neither do I. I don't think I've ever seen the foreach keyword outside
of the documentation. But if you talk about different loop styles you
need a name for this style. Perldoc perlsyn calls it a "foreach loop".
So why should we not stick with that name? (Yes, I know, it's ambiguous:
You could also write "foreach ($i = 0; $i < 10; $i++)" and call that a
"foreach loop", but who would?)

hp
 
P

Peter J. Holzer

Perl references can also be converted to string or integer, and thus can
be ordered.

Yes, but the order isn't meaningful. In C the the order is only defined
for pointers which point into the same object, but for those it is
meaningful.
If you consider Scalar::Util part of the core language (and I do,
since you don't even get reliable equality without it) refs can also
be queried for internal and user-defined type.

Yes. And even without that you can use ref. Although I would argue that
this isn't a feature of the reference but of the referenced object.

hp
 
K

Keith Thompson

Peter J. Holzer said:
I very much suspect that Shmuel knows this.

But the documentation still calls this style of loops "Foreach Loops"
and the C-style loops "For loops".
[...]

I've always found that to be a (rather minor) annoyance in Perl.

If I had designed the language, "for" would be used only for C-style
loops, and "foreach" only for the list form. It's great that there's
more than one way to do it, but I don't see the benefit of having
more than one way to spell it.

Of course changing it now would break existing code.

(Then again, if I had designed the language you probably wouldn't
be using it.)
 

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,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top