(..) and (...) question

M

MSG

According to Perl Cookbook, the three dots (...) should be
"not inclusive" while the two dots (..) "inclusive" when used
with line numbers. By "not inclusive", I would think that the
code below will print only line 2, but it prints the same first
three lines just like using (..). Can someone please explain?
Thanks!

#!perl

use strict;
use warnings;

while ( <DATA> ){
chomp;
if ( 1 ... 3 ){
print $_, "\n";
}
}

__DATA__
Line 1
Line 2
Line 3
Line 4
 
P

Paul Lalli

MSG said:
According to Perl Cookbook, the three dots (...) should be
"not inclusive" while the two dots (..) "inclusive" when used
with line numbers. By "not inclusive", I would think that the
code below will print only line 2, but it prints the same first
three lines just like using (..). Can someone please explain?

I don't have my copy of the Cookbook on me, so I don't know in what
context "inclusive" is used. However, `perldoc perlop` explains it
thusly:

Each ".." operator maintains its own boolean
state. It is false as long as its left operand is false.
Once the left operand is true, the range operator stays true
until the right operand is true, AFTER which the range
operator becomes false again. It doesn't become false till
the next time the range operator is evaluated. It can test
the right operand and become false on the same evaluation it
became true (as in awk), but it still returns true once. If
you don't want it to test the right operand till the next
evaluation, as in sed, just use three dots ("...") instead
of two.

So the difference is that with .., the right operand is evaluated on
the same iteration that the left became true. With ..., it's not
evaluated until the next time around. So to illustrate, based on your
example:
#!/usr/bin/env perl
use strict;
use warnings;

while ( <DATA> ){
if ( 2 .. 2 ){
print "A: $_";
}
if ( 2 ... 2 ){
print "B: $_";
}

}

__DATA__
Line 1
Line 2
Line 3
Line 4

Output:
A: Line 2
B: Line 2
B: Line 3
B: Line 4

(This is all much clearer if you keep in mind that the expressions are
actually shorthand for
$. == 2 .. $. == 2
and
$. == 2 ... $. == 2
respectively)

So, in the first one, the left hand argument evaluated to true, which
made the expression true. But in that same iteration, the right-hand
argument became true, which made the expression true on the *next*
iteration. So only one line was printed.
In the second one, the left hand argument evaluated to true, making the
expression true. And that was it. In the next iteration, $. == 2 was
false, so the right argument remained false, and the overall expression
remained true for the remainder of the loop.

Does that help to explain it at all?

Paul Lalli
 
D

DJ Stunks

MSG said:
According to Perl Cookbook, the three dots (...) should be
"not inclusive" while the two dots (..) "inclusive" when used
with line numbers. By "not inclusive", I would think that the
code below will print only line 2, but it prints the same first
three lines just like using (..). Can someone please explain?
Thanks!

#!perl

use strict;
use warnings;

while ( <DATA> ){
chomp;
if ( 1 ... 3 ){
print $_, "\n";
}
}

__DATA__
Line 1
Line 2
Line 3
Line 4

I don't know which version of the Perl Cookbook you have, but mine does
not say that at all:
The difference between .. and ... is their behavior
when both operands can be true on the same line.
Consider these two cases:

print if /begin/ .. /end/;
print if /begin/ ... /end/;

Given the line "You may not end ere you begin", both the
double- and triple-dot versions of the range operator
above return true. But the code using .. will not print
any further lines. That's because .. tests both conditions
on the same line once the first test matches, and the
second test tells it that it's reached the end of its
region. On the other hand, ... will continue until the
next line that matches /end/ because it never tries to
test both operands on the same time.

-jp
 
E

Eric Amick

According to Perl Cookbook, the three dots (...) should be
"not inclusive" while the two dots (..) "inclusive" when used
with line numbers. By "not inclusive", I would think that the
code below will print only line 2, but it prints the same first
three lines just like using (..). Can someone please explain?
Thanks!

What they meant is that the line causing the first operand to evaluate
to true is not checked against the second operand with the three-dot
range operator. Change the code to 1 ... 1 and you'll get all four lines
printed because the second operand will not be checked against the only
line where it can be true; 1 .. 1, on the other hand, will print just
the first line.
 
B

Bart Lateur

MSG said:
According to Perl Cookbook, the three dots (...) should be
"not inclusive" while the two dots (..) "inclusive" when used
with line numbers. By "not inclusive", I would think that the
code below will print only line 2, but it prints the same first
three lines just like using (..). Can someone please explain?

"3 dots" simply skips the test for the end condition, if the start
condition is met for the first time. "2 dots" tests it the first time,
too.

And numeric literals for the condition is special, I wouldn't test this
distincition with them. Well, you could: try "1 .. 1" vs. "1 ... 1". The
latter never finishes.

Try this more elaborate example:

while ( <DATA> ){
chomp;
if ((/foo/ and print "$.: start condition met\n")
... # or ..
(print "$.: test end condition\n" and /bar/)){
print $_, "\n";
}
}

__DATA__
skip this
food at the bar
more
bart
done

Result with 3 dots:

2: start condition met
food at the bar
3: test end condition
more
4: test end condition
bart

2 dots:

2: start condition met
2: test end condition
food at the bar

As you can see, with 2 dots, the end condition is immediately tested
after the first success of the start condition. With 3 dots, the test is
skipped the first time.
 

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

Staff online

Members online

Forum statistics

Threads
474,121
Messages
2,570,712
Members
47,282
Latest member
hopkins1988

Latest Threads

Top