views:

85

answers:

3

In perl, for numerical comparison, we have +/- inf as numbers that are greater/less than every other number. Are there also strings that are gt/lt any other string?

The reason I ask is that I'd like to tack one or the other on the end of a list of strings to ensure that a loop will terminate before the end of the list.

+4  A: 

No. But "" will be less than or equal to any other string, and chr(~0) repeated sufficient times will be greater than or equal to any string of that length or less. (Assuming you aren't using locale-based collation via 'use locale'.)

(chr(~0) will require no warnings 'utf8', since it's not in the ranges of defined utf8 characters.)

ysth
What is "chr(~0)"?
Ryan Thompson
@Ryan Thompson: ~0 is the one's compliment of 0, the largest integer (and hence the ordinal value of the largest character) perl will use. On 32-bit perls, it will be chr(4294967295), on 64-bit perls, chr(18446744073709551615).
ysth
You shouldn't need to repeat `chr(~0)` at all. Since it's not a valid codepoint, it shouldn't appear in any real data string in your program.
cjm
@cjm: it seems a little hypocritical to say "string x is greater than any string in this program" when string x is in the program :)
ysth
+2  A: 

The empty string or undef is less than every other string.

There is no finite string that is greater than every other string. But if you can make certain assumptions like all of the strings in your loop are ASCII strings, you could specify a string like "\x80" (ASCII value 128) that would be greater than all of your strings.

mobrule
Well, it turns out that I can assume that all my strings are `le "99999999"`, since they're all date strings of the form `YYYYMMDD`.
Ryan Thompson
undef is a silly thing to use, since it will warn when compared to a string.
ysth
I've accepted this answer because it's the best you can do without disabling warnings or writing it yourself.
Ryan Thompson
+3  A: 

Here's a complete implementation with tests for an overloaded string that's greater than any other string. Its a pretty simple overload, why screw around with approximations?

package String::Infinity;

use overload
    '""'  => sub {
        return "Infinity"
    },
    'cmp' => sub {
        my($left, $right, $reverse) = @_;
        return 0 if ref $right && $right->isa("String::Infinity");
        return $reverse ? -1 : 1;
    },
    fallback => 1
;

sub new {
    my $class = shift;
    return bless \Inf, $class;
}


use Test::More;

my $inf = String::Infinity->new;
is "$inf", "Infinity",  "stringification";
ok $inf eq $inf,        "equals itself"; 
ok $inf ne "foo",       "  doesn't equal anything else";
ok $inf ne "Infinity",  "  even what it stringifies to";
ok $inf gt "lfkdlk",    "  greater than";
ok !$inf lt "lkafj",    "  not less than";
is $inf cmp "lkjd", 1,  "  cmp";
is "ldfjal;kjd" cmp $inf, -1,   "  cmp reversed";

done_testing;
Schwern
Why? Because I'm not (yet) enough of a perl guru to have experience writing classes that overload operators. That's pretty neat, though.
Ryan Thompson