[HN Gopher] The ordering operators
       ___________________________________________________________________
        
       The ordering operators
        
       Author : Amorymeltzer
       Score  : 27 points
       Date   : 2022-04-07 09:52 UTC (2 days ago)
        
 (HTM) web link (blogs.perl.org)
 (TXT) w3m dump (blogs.perl.org)
        
       | tialaramex wrote:
       | Interesting, why is there a separate operator for strings?
       | 
       | Are there scenarios when either operator (cmp or <=>) works, but
       | they have different behaviour?
        
         | adrianmonk wrote:
         | Perl doesn't have a way to say "this value is a number" or
         | "this value is a string".
         | 
         | Instead, the two are effectively the same type (which Perl
         | calls a scalar value), and you use different operators to treat
         | them like strings or numbers as desired.
         | 
         | So, for example, you can do something like this:
         | # declare $a and initialize it with a literal         #
         | numerical value of 3.          my $a = 3;              # switch
         | gears and treat it like a string         # instead of a number
         | by appending an "X".         $a .= "X";              # output a
         | line that says "3X".         print "$a\n";
         | 
         | Or like this:                   # declare $b and initialize it
         | with a literal         # string value of "l33t".         my $b
         | = "l33t";              # do a regex substitution (string
         | operation)         # to remove letters. New string will be
         | "33".         $b =~ s/[a-z]//g;              # multiply string
         | "33" times 3.         $b *= (1 + 1 + 1);              # output
         | a line that says "99".         print "$b\n";
         | 
         | So, if you have an array of scalar values like "123" and "5",
         | Perl doesn't know whether to sort these as numbers (5 goes
         | first) or as strings ("123" goes first) because the value isn't
         | necessarily a string or a number.
        
           | heresie-dabord wrote:
           | > Perl doesn't have a way to say "this value is a number" or
           | "this value is a string".
           | 
           | use Scalar::Util qw(looks_like_number);
           | 
           | #example
           | 
           | if(looks_like_number($value)) { say "$value is a number"; }
        
             | a1369209993 wrote:
             | my @chips = ("74HC08","8085AH","555","7C199-15");
             | use_value($_) foreach @chips;
             | 
             | 555 is a number; "555" is not a number.
        
             | jwilk wrote:
             | But looks_like_number("42") is still true.
             | 
             | OTOH, JSON::PP can tell the difference between string and
             | number:                 $ perl -MJSON::PP -E 'say
             | JSON::PP::encode_json(42);'       42            $ perl
             | -MJSON::PP -E 'say JSON::PP::encode_json("42");'       "42"
        
         | bewuethr wrote:
         | Yes, when you compare numbers lexically, "cmp" will say that 2
         | sorts after 10, and "<=>" will say it sorts before:
         | perl -e 'printf "%d %d\n", 2 <=> 10, 2 cmp 10'
         | 
         | prints                 -1 1
        
         | darrenf wrote:
         | > _Are there scenarios when either operator (cmp or <=>) works,
         | but they have different behaviour?_
         | 
         | It being Perl, you can basically throw anything at either
         | operator if you like. It's trivial to find examples where the
         | answers are different:                    perl -wlE 'say "a"
         | <=> "b"; say "a" cmp "b";'         Argument "b" isn't numeric
         | in numeric comparison (<=>) at -e line 1.         Argument "a"
         | isn't numeric in numeric comparison (<=>) at -e line 1.
         | 0         -1
        
       | ilyash wrote:
       | For comparison, in Next Generation Shell, the above would be
       | solved as follows:                   version_ok =
       | version.split(".").map(Int) >= [3, 6, 8]
        
         | tedmiston wrote:
         | NGS looks interesting as a Bash alternative.
         | 
         | https://github.com/ngs-lang/ngs
        
       | mcphage wrote:
       | Can you use <=> on arrays in Perl? In ruby that would be [$maj,
       | $min, $rel] <=> [3, 6, 8]
        
         | smueller1234 wrote:
         | At least in Perl 5 (which TFA uses), you can not. Or certainly
         | not expect a useful result.
         | 
         | https://perldoc.perl.org/perlop#Relational-Operators
        
           | toast0 wrote:
           | It says a numerical comparison, so it will compare only the
           | length of the arrays.
        
       | samatman wrote:
       | <=> has some of the semantics of Fortran's "arithmetic" IF
       | statement.
       | 
       | This can be useful, as the Fine Article shows, in sorts and
       | searches, I've rolled it by hand a few times for tests like "is
       | this offset in the line we're examining".
        
         | omoikane wrote:
         | <=> and cmp also have the benefit that fewer comparisons are
         | done. It might not be that big a deal for Perl scalars, but for
         | C++, an overloaded operator< that does something like this:
         | return left.a != right.a ? left.a < right.a
         | : left.b < right.b;
         | 
         | That might result in exponential number of compare operations
         | if those nested comparisons are also overloaded, whereas with
         | <=> (as of C++20), the number of compare operations can be made
         | to be linear:                  return left.a <=> right.a < 0 ||
         | left.b <=> right.b < 0;
        
       ___________________________________________________________________
       (page generated 2022-04-09 23:02 UTC)