Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I use Perl's scalar range operator?

Tags:

range

perl

scalar

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
like image 343
Eugene Yarmash Avatar asked Jan 27 '10 12:01

Eugene Yarmash


People also ask

How do you use a range operator?

You can use the range operator to create a list with zero-filled numbers. To create an array with ten elements that include the strings 01, 02, 03, 04, 05, 06, 07, 08, 09, and 10 do: @array = ("01".."10"); And you can use variables as operands for the range operator.

Which operator can be used to define range?

The range operator ( [] ) is used to indicate a character class. A character class is a range of characters that may be used in the current regular expression to match. This character class matches a single character, regardless of how many characters are defined within the character class.

What is range operator in Perl?

range operator is really two different operators depending on the context. In a list context, it returns a list of values counting (by ones) from the left value to the right value. In a scalar context, .. returns a Boolean value. It is false as long as its left operand is false.

What does ~~ mean in Perl?

It is the smartmatch operator.


3 Answers

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);
}
like image 166
Greg Bacon Avatar answered Sep 21 '22 10:09

Greg Bacon


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.

like image 22
NO WAR WITH RUSSIA Avatar answered Sep 19 '22 10:09

NO WAR WITH RUSSIA


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;
}
like image 25
daotoad Avatar answered Sep 22 '22 10:09

daotoad