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

Unlike pretty much any other function that returns 'false' in Perl, meaning 0 or a negative number of undef, the index() function returns the '-1' string rather than the actual number -1. Go ahead, try this out. I bet it doesn't do what you would expect:
my $string = 'string here'; my $index = index $string, 'bah'; print $index if $index;
Believe it or not, you actually have to force a numeric context to get it to work:
print $index if $index >= 0;
Beware of this one when using index as a faster alternative to regular expressions when simply checking for keywords in a string. The following is particularly subtle and annoying:
if (my $index = index $string, $key) { # yadda }
That block of 'if' code will always be executed. And here I thought I'd run into my last internal perl bug, reminds me of the 90s again.

Replies are listed 'Best First'.
Re: Perl index() Function Returns String, Not Numeric
by ikegami (Patriarch) on Aug 19, 2006 at 07:26 UTC

    index doesn't return true/false because we need to distinguish the result of index('abcde', 'xyz') from the result of index('abcde', 'abc'). The language designer(s) chose to use -1 (well, $[ - 1) to signal "no match". The return value is documented. undef might have been a better choice, but it still wouldn't allow the syntax you attempted to use.

    If you wish to use index in the if expression, you can do the following:

    if ((my $index = index $string, $key) >= 0) { ... }

    Believe it or not, you actually have to force a numeric context to get it to work:

    >= 0 doesn't just force numerical context. It also check if the number is positive. 0+$index would force numerical context, but it doesn't help here because index doesn't care about context. index always returns a number.

    use Devel::Peek qw( Dump ); Dump(index('abcdef', 'abc')); # IOK ==> number Dump(index('abcdef', 'xyz')); # IOK ==> number

    Unlike pretty much any other function that returns 'false' in Perl, meaning 0 or a negative number or undef

    Negative is never considered false. Perl considers the following (and only the following) false: Zero (0, 0EO, etc), the string consisting of just the character zero ("0"), the empty string (""), the undefined value (undef) and things which evaluate to that listed when in scalar context.

    Update: Tweaks throughout.

      More specifically than scalar context, boolean context. The distinction can matter a lot, particularly if overload has been used.
Re: Perl index() Function Returns String, Not Numeric
by tilly (Archbishop) on Aug 19, 2006 at 07:16 UTC
    This is not a bug and your surprise indicates that you have major misconceptions about what values Perl considers true. See the documentation to clear that up.
Re: Perl index() Function Returns String, Not Numeric
by rodion (Chaplain) on Aug 19, 2006 at 10:44 UTC
    If you really need a function which gives you the truth value of m//, but returns the index, you can always write something like
    sub match_index { my $pos; return (($pos =index($_[0],$_[1]))<0) ? 0 : ($pos == 0) ? '0 but true' : $pos; }
    Note that "0 but true" is special syntax that does not emit a warning when you add 1 to it. "0 but True" or "0 but TRUE" don't have this property.

    On the machine I'm on right now, the sub takes less than a microsecond, so you have to be doing a lot of matches for it to matter. (m// takes a quarter of that time, and index() takes an eighth.)

    If the problem is just that index() didn't work like you expected it to, then, as the others suggest, you need to change what you expect. For what it's worth, both index() and m// work as I expect them to work, and my sense of the other posters so far is that that's mostly true for them. As they say in the U.S. auto business, "Your milage may vary."

      I have been known to write '0 but true' as '0.0'.
        We had a poll which listed a number of "true zeros".
Re: Perl index() Function Returns String, Not Numeric
by BrowserUk (Patriarch) on Aug 19, 2006 at 11:22 UTC

    Most of my uses of index look something like

    if( $p = 1+index( $str, $sought ) ) { ## Do something with $p ## remembering that it's +1 ## but most times, that what you want anyway. }

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Perl index() Function Returns String, Not Numeric
by chromatic (Archbishop) on Aug 19, 2006 at 19:13 UTC
    Unlike pretty much any other function that returns 'false' in Perl, meaning 0 or a negative number of undef, the index() function returns the '-1' string rather than the actual number -1.

    Yes, and that's to avoid the semipredicate problem. (Without warnings enabled, evaluate undef + 0 and see what you get.)

    I have no idea what your title means though; it's just wrong.