How should I use Perl's scalar range operator?

2019-06-17 02:49发布

问题:

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

回答1:

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);
}


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



回答3:

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


回答4:

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