in reply to Re: Pearls (not really) of Perl programming
in thread Pearls (not really) of Perl programming

This is not that baroque once you grasp how the writer is approaching the sort. I looked at this quickly and knee-jerked that the logical expression is Wrong then I realized that it was in a sort block.

The writer is using short-circuiting to exit the block with -1 or 1 values; so that listtype sorts before listcode before funclist before every thing else.

I don't write that way. This seems to rely on luck as the block may yield "" which sort is not advertised to accept. I think it needs a catch-all  or ( $a cmp $b ).

Be well.

Replies are listed 'Best First'.
Re^3: Pearls (not really) of Perl programming
by ysth (Canon) on Nov 24, 2004 at 23:53 UTC
    This seems to rely on luck as the block may yield "" which sort is not advertised to accept.
    That code always returns 1 or -1 AFAICT. Can you explain?

    Update: it will return false if $a or $b isn't any of the types tested for, but false isn't "", it's both 0 and "":

    $ perl -we'@_ = sort { "" } 1,2' Sort subroutine didn't return a numeric value at -e line 1. $ perl -we'@_ = sort { !1 } 1,2'
      Thanks for the correction. It was my error to be seduced by the control flow like use of logical short circuiting to the point of thinking statements instead of an expression. More succinctly: I had another braindead moment.

      Now that you've drawn my attention to the code again. I say it is that baroque. My initial justification was just for the  and 1 stuff which I still don't find so bad.

      I would still like a or $a cmp $b or a or 0 or  die "domain err". It is not readily apparent what is to happen with other/other comparisions. This seems like a significant decision point in the code (by the identifiers) and so a good place for extra clarity. I can imagine myself referring to this snippet to understand how all the subsequent parsing code is recieving data. This may be such a recurring problem in the codebase that it seems unimportant.

      What does irk is the inconsistent use of short-circuiting, the sub-clauses are unnecessary and so confusing. (I just trusted that aspect the first time around.

      If I were going to write in that form I'd write something like:

      @List = sort { $a eq "one" and -1 or $b eq "one" and 1 or $a eq "two" and -1 or $b eq "two" and 1 # no need to check if $a eq one or $a eq "thr" and -1 or $b eq "thr" and 1 or 0 # advertising the default case }
      Be well.
      Although you give examples of strange code and it does not pretend to be good, I can't resist pointing that:

      code block given to sort must behave (as POD stays.)
      Namely, once f(a,b) return false f(b,a) must return true.
      Some versions of perl dumped core when fed some misbehaving comparision sub.
      Such core dumps were fixed, but general rule remain: comparision sub must behave

      This means that sort {rand(5) <=> rand(5)} is obviously wrong, but sort {1} also not good.

      Best regards,
      Courage, the Cowardly Dog

        The comparison function for sort must not just return 'true' and 'false'.
        It must return '-1', '0' and '+1' for comparing 'Less Than', 'Equal To' and 'Greater Than', just like the two standard comparison operators 'cmp' and '<=>' (for stringwise and numeric comparison respectively).

        Just using 'true' (ie non-zero, probably 1) and false (ie 0 or '') will lead to confusion.

        If f(a, b) is 'false' then f(b, a) must also be false because a 'Equals' b - for whatever value of 'Equals' this sorting choses to use.
        If f(a, b) is 'true' then f(b, a) must return '-1' (ie a true value, but *not* just true) because a is 'Greater Than' b in this case, and therefore b must be 'Less Than' a - not 'Equal To', or something is decidedly wierd.

        You have to be consistent however you chose to do it.

        To clarify, prior to perl 5.005 (!) sort used to use libc's qsort, which would sometimes coredump on certain platforms with pathological return values. But this isn't a concern any longer unless you are stuck with a really old perl.