8

What is the scalar ".." operator typical usage? Is it only selecting blocks of text?

Interesting example by myself:

sub get_next {
    print scalar($$..!$$), "\n";
}

get_next for 1 .. 5;  # prints numbers from 1 to 5
get_next for 1 .. 5;  # prints numbers from 6 to 10
brian d foy
  • 129,424
  • 31
  • 207
  • 592
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 3
    I had never used it and didn't knew too :(. Googling for your question came up with this nice article in perlmonks:http://www.perlmonks.org/?node_id=377450 A lesson for me too :) – sateesh Jan 27 '10 at 12:50
  • @sateesh, your comment is really an answer (and a good reference to boot) – ericslaw Jan 27 '10 at 13:25
  • 3
    See also http://stackoverflow.com/questions/2143554/is-perls-flip-flop-operator-bugged-it-has-global-state-how-can-i-reset-it – Sinan Ünür Jan 27 '10 at 14:12
  • 1
    It's for whatever job you decide it should do for you. It's just one of the tools in the toolbox. Don't go looking for excuses to use it, but when you find a job for it, you know where to find it. :) – brian d foy Jan 27 '10 at 15:57
  • Sinan Ünür: interesting indeed. added it to favorites! – Eugene Yarmash Jan 27 '10 at 18:16
  • 1
    Yes, that was my post. This operator sucks, it is cute and amusing, and a decent idea but the current implementation requires you to have another mental model of of how operators work. It shouldn't maintain state like it does. – Evan Carroll Jan 27 '10 at 18:40

4 Answers4

3

People hardly seem to know about it based on questions here, but, yes, I'd say typical usage is selecting blocks of text, either with

while (<>) {
  print if /BEGIN/ .. /END/;
}

or

while (<>) {
  print if 3 .. 5; # prints lines 3 through 5
}

The latter is syntactic sugar for checking against the input line-number ($.)

... if $. == 3 .. $. == 5;

which suggests the weird-looking

#! /usr/bin/perl -l

for ($_ = 1; $_ <= 10; ++$_) {
  print if $_ == 4 .. $_ == 7;
}

The above program's output is

4
5
6
7

If you have some sort of bracketing condition, test for it in subs:

for (...) {
  do_foo($x,$y,$z) if begin($x) .. end($z);
}
Greg Bacon
  • 134,834
  • 32
  • 188
  • 245
2

Outside of perl -e you really shouldn't. It is esoteric and funky. See my post not even 24hrs ago about it about how it maintains state with calling context. This stung me in a real world application, because I was trying to be clever and found what I thought was a good use-case for it.

Community
  • 1
  • 1
Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
2

Here's a place where you need to be very careful about unintentional use of the scalar range operator: subroutine returns.

sub range {
     my $start = shift;
     my $end   = shift;

     return $start .. $end;
}

@foo = range( 1, 5 );  # ( 1, 2, 3, 4, 5 )
$foo = range( 1, 5 );  # False or maybe true.  Who knows.

If you call this subroutine in scalar context, you'll be in for a surprise.

After being bitten by some variant of this problem, I now always make sure I assign a list return into an array, thereby getting array-like context behaviors for my subs. If I need other context specific behavior (very rarely) I use wantarray.

sub range {
     my $start = shift;
     my $end   = shift;

     my @result = $start .. $end;
     return @result;
}
daotoad
  • 26,689
  • 7
  • 59
  • 100
0

another use is simple counters like this: perl -e 'foreach ( 1 .. 100 ){print"$_\n"}'

biegleux
  • 13,179
  • 11
  • 45
  • 52
ericslaw
  • 851
  • 1
  • 8
  • 16