From: Ben Morrow on

Quoth Mart van de Wege <mvdwege(a)mail.com>:
> >
> > my @lines;
> > my $limit = 3;
> > for my $line(1..$limit) {
> > $lines[$line] = <IN>
> > }
> >
> > But then again I have a personal dislike of counters and flags, so I
> > tend to look for ways to avoid using them.
>
> And that was an off-by-one error. Saw it as I hit 'post'.
>
> So the correct code would of course be:
>
> my @lines;
> my $limit = 3;
> for my $line(0..$limit-1) {
> $lines[$line] = <IN>
> }

Better would be

my @lines;
push @lines, <IN> for 1..3;

though I would probably rather have

my @lines = map <IN>, 1..3;

since I don't like variable declarations just hanging around not doing
anything useful.

Ben

From: Willem on
Ben Morrow wrote:
) Better would be
)
) my @lines;
) push @lines, <IN> for 1..3;
)
) though I would probably rather have
)
) my @lines = map <IN>, 1..3;
)
) since I don't like variable declarations just hanging around not doing
) anything useful.

BZZT!

Both of your examples will read the entire file into @lines.
Left as an exercise to figure out why this is and how to fix it.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
From: Willem on
Ben Morrow wrote:
) 'They' in this case being me? I wasn't trying to be clever, I was trying
) to write the code in a simple and obvious way. Counting indices by hand
) is much easier to get wrong than letting perl count them for you.

You mean like: for (0..2) { $lines[$_] = <IN> }

But in any case, this mistake is not a cleverness one,
because the exact same problem exists in the code:

for (my $i = 0; $i < 3; $i++) {
push @lines, <IN>;
}

Which I would hardly call 'clever'.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
From: Marc Girod on
On Jun 8, 9:14 pm, Willem <wil...(a)turtle.stack.nl> wrote:

> You mean like: for (0..2) { $lines[$_] = <IN> }

I'am not smart enough to not try being clever.
Besides (and for wrong reasons: I used to like Lisp), I like maps.
So, I was thinking of the following minimal(?) fix(?):

my @lines = map scalar <IN>, 1..3;

Marc
From: Ben Morrow on

Quoth Willem <willem(a)turtle.stack.nl>:
> Ben Morrow wrote:
> ) 'They' in this case being me? I wasn't trying to be clever, I was trying
> ) to write the code in a simple and obvious way. Counting indices by hand
> ) is much easier to get wrong than letting perl count them for you.
>
> You mean like: for (0..2) { $lines[$_] = <IN> }

Mmm, I suppose. I think my problem with that is that I just dislike
array indices other than [0] and [-1]: I think of arrays as 'frozen
lists', so either you iterate over the whole thing or you attack it from
the ends.

The original buggy code was essentially

for (1..3) { $lines[$_] = <IN> }

and the use of explicit subscripts disguises the fact that there's an
extra 'undef' element on the beginning.

> But in any case, this mistake is not a cleverness one,
> because the exact same problem exists in the code:
>
> for (my $i = 0; $i < 3; $i++) {
> push @lines, <IN>;
> }
>
> Which I would hardly call 'clever'.

I suspect that anyone approaching that code who didn't have a background
in C *would* call it clever, or at any rate much more complicated and
less comprehensible than a simple

for (1..3)

Something like

repeat (3) {...}

would be even simpler, of course, but unfortunately Perl doesn't allow
modules to create new syntax like that[0].

Ben

[0] ...without support code that will make you go blind.
c.f. Devel::Declare, and/or source filters.