plendid has asked for the wisdom of the Perl Monks concerning the following question:

Hello Dear Monks,

An elementary question for your response. I'm attempting to succinctly determine if $frequency falls between 10 and 15. Why doesn't,

my $frequency = 12; if ($frequency == 10 .. 15) {print "Yes"}

return "Yes"?

Replies are listed 'Best First'.
Re: querying a range of values
by Marshall (Canon) on Jan 12, 2010 at 22:42 UTC
    The right way to decide if some value is between say 10 and 15 is to use 2 compares and "AND" the result together. The value must be >=10 AND <=15. Below I used the && operator instead of "and" which would have worked also. There is a difference in precedence between these 2 operators either one will work with the statement as I have written it.

    In order to get your code to print "Yes", I set $frequency = 10. This winds up meaning: "if ($frequency == 10 ...some not understandable stuff, hence the error message)".

    The "==" operator means exactly "equal to".

    I recommend always enabling warnings, either by the "shebang line" #!/usr/bin/perl -w or the statement "use warnings;". "use strict" is also an extremely good idea.

    You would have seen immediately that Perl didn't like your "if" statement.

    #!/usr/bin/perl -w use strict; my $frequency = 10; if ($frequency == 10 .. 15) #this is line 5 {print "Yes freq 10 is ok!(or maybe not quite right!)"} print "\n"; $frequency = 12; if ( (10 <= $frequency) && ($frequency <=15 ) ) { print "Yes $frequency is ok!\n"; } __END__ prints: Use of uninitialized value $frequency in range (or flop) at C:\TEMP\compare.pl line 5. Yes freq 10 is ok!(or maybe not quite right!) Yes 12 is ok!

      Nicely done. Thank you all for advice and insight.

      I think that i'll opt for smart quotes for now.

Re: querying a range of values
by jwkrahn (Abbot) on Jan 12, 2010 at 21:45 UTC

    Because the flip-flop operator will only return true or false and will never equal 10, 11, 12, 13, 14 or 15.    You need something like:

    if (grep $frequency == $_, 10 .. 15) {print "Yes"}
Re: querying a range of values
by Anonymous Monk on Jan 12, 2010 at 21:40 UTC
    Maybe you're thinking of the smart match operator?
    use 5.010; for my $frequency ( 1, 10 .. 17 ){ print $frequency, ' '; if ($frequency ~~ [ 10 .. 15 ]) {print "Yes"} print "\n"; } __END__ 1 10 Yes 11 Yes 12 Yes 13 Yes 14 Yes 15 Yes 16 17
Re: querying a range of values
by toolic (Bishop) on Jan 12, 2010 at 21:46 UTC
    First, a succinct way to do this is to use the between function from Acme::Tools:
    use Acme::Tools; if (between($frequency, 10, 15) {print "Yes"}
    I believe your code does not print Yes due to operator precedence. My guess is that
    if ($frequency == 10 .. 15) {print "Yes"}
    is the same as:
    if ( ($frequency == 10) .. 15 ) {print "Yes"}
    in which case, the left side of the .. operator ($frequency == 10) is false, and in that case the whole expression is false. Refer to Range Operators.

    Update: add another example...

    If you set it to 10, you will get a Yes:

    my $frequency = 10; if ($frequency == 10 .. 15) {print "Yes"}
    but, you will get a warning if you use warnings; In any case, you should not try to use .. this way.

      The  .. operator in scalar context is the flip-flop operator, not the range operator.

        The .. operator in scalar context is the flip-flop operator, not the range operator.
        Firstly, I never explicitly named the .. operator in my post; I merely linked to the Perl official documentation which describes the .. operator, titled Range Operators.

        Secondly, the documentation appears to disagree with your assertion that .. in scalar context is not the range operator (emphasis is mine):

        In scalar context, ".." returns a boolean value. The operator is bistable, like a flip-flop, and emulates the line-range (comma) operator of sed, awk, and various editors. 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. In all other regards, "..." behaves just like ".." does.
        You may refer to the operator however you wish, but it is correct to refer to it as the "range operator" in all contexts, including scalar context.