fromIndex for String.prototype.search

Steven Levithan steves_list at hotmail.com
Sun Apr 22 08:40:53 PDT 2012


I should add that the reason for showing my code was to illustrate that it’s easy to apply firstIndex/pos and even /y flag emulation without the string slicing on each iteration that you worried about, by using exec with /g and lastIndex (ugly though it may be).

--Steven Levithan


From: Steven Levithan 
Sent: Sunday, April 22, 2012 12:56 AM
To: Felix Böhm ; es-discuss at mozilla.org 
Subject: Re: fromIndex for String.prototype.search

Adding a firstIndex argument to string.search seems like an incomplete proposal to me. IMO, if it were to be added there, it should also be added at least to regexp.test, regexp.exec, and string.match when given a nonglobal regex (in which case it’s an alias for regexp.exec). It could also be useful, though probably far less frequently, with string.split, string.replace, and string.match (when given a global regex).

Using regexp.lastIndex together with regexp.exec and /g in order to pull this off is indeed ugly (and runs into issues with IE8-minus for zero-length matches), but at least it provides a mechanism that lets you build your own sugar.

The “^” metacharacter (and potential future regex syntax) is not the only thing to consider if adding an alternative mechanism to set the starting position for a regex. There is also the interplay with flag /y (no biggie, just something to keep in mind), and more importantly the conflict with the lastIndex property for global regexes. I’d like to see both the lastIndex and global properties of regexps be deprecated altogether, in which case what you’re pitching would be perfectly reasonable. But that would require broader changes, and I don’t expect such ideas to be tackled (much less see TC-39 consensus) in time for ES6.

In the XRegExp library, I provide an argument like you’re proposing for my own exec and test methods, but this can only be done cleanly since I always ignore lastIndex as the search start position. Here’s the code, in case you’re interested. (The private `copy` function used here accepts flags to add via the second arg, and flags to remove via the third arg.)

XRegExp.exec = function (str, regex, pos, sticky) {
    var r2 = copy(regex, "g" + (sticky && hasNativeY ? "y" : ""), (sticky === false ? "y" : "")),
        match;
    r2.lastIndex = pos = pos || 0;
    match = fixed.exec.call(r2, str); // Fixed `exec` required for `lastIndex` fix, etc.
    if (sticky && match && match.index !== pos) {
        match = null;
    }
    if (regex.global) {
        regex.lastIndex = match ? r2.lastIndex : 0;
    }
    return match;
};

--Steven Levithan


From: Felix Böhm 
Sent: Friday, April 20, 2012 2:20 PM
To: es-discuss at mozilla.org 
Subject: fromIndex for String.prototype.search

In December of 2009, there was already a related proposal [1] (which pretty much got ignored at that time), but I wanted to ask only for a subset of it:

When building parsers, the second argument of String.prototype.indexOf (named firstIndex) is pretty helpful to speed things up. A simple index can be used to track the current position. In more general cases (with more than just a handful of separators), String.prototype.search appears to be the better choice. But lacking the firstIndex parameter, it requires to use String.prototype.substr after each iteration. This leads to slow and bad-looking code. But there's a solution: A firstIndex parameter for String.prototype.slice.

A polyfill could look like this (expecting that the number of arguments is increased to 2):

if (String.prototype.search.length === 1) {
    String.prototype.search = (function (oldSearch) {
        return function (re, fromIndex) {
            if (typeof fromIndex !== "number") return oldSearch.call(this, re);
            var result = oldSearch.call(this.substr(0, fromIndex), re)
            return result === -1 ? result : result + fromIndex;
        };
    })(String.prototype.search);
}

The only reason I can think of why this might be a bad idea is the "^" metacharacter, as it's accepting the new position as the start of the string. The optimal/expected behavior in this case might need some discussion (even though the solution above eases polyfilling a lot).

The only response to the old proposal suggested using re.lastIndex, what's just ugly and feels hacky.

[1] https://mail.mozilla.org/pipermail/es-discuss/2009-December/010505.html


--------------------------------------------------------------------------------
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss



--------------------------------------------------------------------------------
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120422/09ef353e/attachment.html>


More information about the es-discuss mailing list