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

The following worked fine on Linux, but is not working on Win7 Pro (Strawberry Perl 5.18.2 64bit)

(This uses the expression form of grep)

#!perl -w use warnings; use strict; my @times = ( 1, 2, 3, 4); print STDERR "Times: @times\n"; if (grep ((0 + $_) >= 99999999), @times) { die('Time values must be < +99999999'); }

Output:

>perl ptest.pl Times: 1 2 3 4 Time values must be < 99999999 at ptest.pl line 9. >

Replies are listed 'Best First'.
Re: compare always true in grep
by ikegami (Patriarch) on Oct 24, 2014 at 18:42 UTC

    The problem is that you used the following grep:

    grep((0 + $_) >= 99999999)

    You meant to use the following grep:

    grep(((0 + $_) >= 99999999), @times)

    Be careful when you omit parens around arguments.


    You must have had different code on your linux system. Side-effects aside,

    if (EXPR, @times) { ... }
    is the same thing as
    if (@times) { ... }
    on all platforms.

    Note that

    grep(EXPR)
    was a syntax error before 5.18. In 5.18, it was changed to be equivalent to
    grep(EXPR, @empty)

    The mentions of a syntax error by the other posters is not relevant to the question; they're simply using an older version of Perl than the versions present on each of your systems.

      Apparently, the Perl on the Linux PCs is even older. I won't be able to check until sometime tomorrow because they are busy running robots.

      Anyway, adding parens around the arguments fixed it.

      Thanks

Re: compare always true in grep
by Laurent_R (Canon) on Oct 24, 2014 at 18:56 UTC
    If you remove the extra parens (+ has a higher precedence than >), it seems to work:
    $ perl -e ' use warnings; use strict; my @times = ( 1, 2, 3, 4); print STDERR "Times: @times\n"; if (grep 0 + $_ >= 99999999, @times) { die("Time values must be < 9999 +9999"); } ' Times: 1 2 3 4 $ perl -e ' use warnings; use strict; my @times = ( 1, 2, 3, 4); print STDERR "Times: @times\n"; if (grep $_ + 0 >= 99999999, @times) { die("Time values must be < 9999 +9999"); } ' Times: 1 2 3 4 $ perl -e ' use warnings; use strict; my @times = ( 1, 2, 3, 999999999999); print STDERR "Times: @times\n"; if (grep $_ + 0 >= 99999999, @times) { die("Time values must be < 9999 +9999"); } ' Times: 1 2 3 999999999999 Time values must be < 99999999 at -e line 8.
    But I would advise you to use the block form of grep in such a case
Re: compare always true in grep
by toolic (Bishop) on Oct 24, 2014 at 18:16 UTC
    I get a syntax error (albeit on a different version):
    perl ptest.pl Not enough arguments for grep at ptest.pl line 9, near "99999999)" Execution of ptest.pl aborted due to compilation errors. perl -v This is perl 5, version 12, subversion 2 (v5.12.2) built for x86_64-li +nux

    Tip #6 from the Basic debugging checklist: B::Deparse

    perl -MO=Deparse ptest.pl Not enough arguments for grep at ptest.pl line 9, near "99999999)" ptest.pl had compilation errors. use warnings; use strict 'refs'; my(@times) = (1, 2, 3, 4); print STDERR "Times: @times\n"; if (grep, @times) { die 'Time values must be < 99999999'; }

      the deparse on Windows is:

      if (grep((0 + $_ >= 99999999)), @times)

      Which looks like the expression parser is stricter than the one in the Perl on the Linux PC.

      In a factory right now, and the Linux PCs are currently busy running robots, so I can't check until the next change over, sometime tomorrow. (Also can't access my office PCs until I get back to the office)

Re: compare always true in grep
by crashtest (Curate) on Oct 24, 2014 at 18:52 UTC

    My 5.18.2 on Linux dies the same way. B::Deparse shows this interpretation of your if statement:

    if (grep((0 + $_ >= 99999999)), @times) {
    Note the parentheses. That is, you have a scalar comma expression with the grep and the @times array, which evaluates to @times. The grep is evaluating the expression 0 + $_ >= 9999999 on an empty list, but that's irrelevant.

    Adding the parentheses properly works:

    if (grep (((0 + $_) >= 99999999), @times)) { ... # prints: Times: 1 2 3 4

Re: compare always true in grep
by Anonymous Monk on Oct 24, 2014 at 18:38 UTC

    Also fails on Linux as listed previously; here perl is v5.16.3. What is your perl version on Linux?

      5.18.0 or higher. That's when

      grep(EXPR)
      become a valid equivalent to
      grep(EXPR, @empty)

        Since you mention it, could you also summarize why? Seems a bad idea to me. I mean, we have a case right here where it would have caught a mistake. What is the point of allowing people to write useless constructs, especially when it is easy to write them by accident?

        - tye