Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #21115
| Message-ID | <3573991.qt74eh6WeI@PointedEars.de> (permalink) |
|---|---|
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
| Organization | PointedEars Software (PES) |
| Date | 2013-08-30 16:00 +0200 |
| Subject | Re: Recommendation for new RegExp (Array-extra-like) methods |
| Newsgroups | comp.lang.javascript |
| References | <ac07e89f-90ee-4b6d-a524-5adfadd0cb94@googlegroups.com> |
brettz9@gmail.com wrote:
> I'd be interested to see a way to get over the requirement for writing
> patterns like this:
>
> while ((matches = regex.exec(str)) !== null) {
Why, and what is the use-case for your proposal?
> I envisioned solving this through an API that could work like this:
>
> (/^(.*?): (.*)$/m).forEach('key1: val1\nkey2: key2',
Whereas your RegExp.prototype.forEach() is:
| function _mixinRegex (regex, newFlags, newLastIndex) {
| newLastIndex = newLastIndex === undefined ? regex.lastIndex :
| newLastIndex;
“undefined” is not read-only in less recent implementations. Use the
“typeof” operator instead.
| newFlags = newFlags || '';
See below.
| regex = new RegExp(
| regex.source,
| (newFlags.indexOf('g') > -1 ? 'g' : regex.global ? 'g' : '') +
| (newFlags.indexOf('i') > -1 ? 'i' : regex.ignoreCase ? 'i'
| : '') +
| (newFlags.indexOf('m') > -1 ? 'm' : regex.multiline ? 'm'
| : '') +
| (newFlags.indexOf('y') > -1 ? 'y' : regex.sticky ? 'y' :
| '') // Non-standard but harmless if already being used
| );
| regex.lastIndex = newLastIndex;
| return regex;
| }
|
| RegExp.prototype.forEach = function (str, cb, thisObj) {
| var matches, n0, i = 0, regex = _mixinRegex(this, 'g');
| thisObj = thisObj || null;
Should be
if (typeof thisObj == "undefined")
{
thisObj = null;
}
| while ((matches = regex.exec(str)) !== null) {
| n0 = matches.splice(0, 1);
| cb.apply(thisObj, matches.concat(i++, n0));
| }
| };
As you are wrapping RegExp.prototype.exec(), you have to create a new RegExp
instance with _mixinRegx() in order to prevent this from running forever.
Because you cannot rely on the global modifier being set on the “this”
value, and you cannot set it afterwards (the “global” property is read-only,
a poor design choice in ES, IMHO). So on *each* call of your
RegExp.prototype.forEach() there is yet another object created, and all the
property fixes required then are performed, needlessly.
| function (key, val, i, n0) {
| document.writeln('key is ' + key + ', value is ' + val + ', and the
| iteration count is ' + i + '<br>');
| });
|
| I have this and other such Array-extra-like methods added to
| RegExp.prototype at https://gist.github.com/brettz9/6366721 (live at
| http://brett-zamir.me/tests/proposal-regexp-extensions.html ) as a kind of
| proof-of-concept.
This is _not_ the Web. It would have been better had you also posted some
code here.
> Might something like this that makes global exec iteration more functional
> be possible as a new addition to the next ECMAScript standard?
Possible, yes; likely, no. Consider that function calls are among the most
expensive constructs, and there is no reason why a second RegExp instance is
necessary here other than syntactic sugar. [I think introducing
Array.prototype.forEach() was a mistake to begin with. It would have been
better to adopt E4X's “for each”. But when you have John Resig of all
people as “JavaScript Evangelist” at Mozilla, what do you expect? jQuery is
strewn with inefficiencies like this, and so is all jQuery-based code.]
You might instead find my jsx.regexp.RegExp useful, which among other
features allows you to name subpatterns and access by that name the
corresponding matches:
/* ?<Perl> style; also supports ?'Perl' style and ?P<ython> style */
var regex = new jsx.regexp.RegExp("^(?<first>.+?): (?<second>.+)$", "mg"),
str = "key1: val1\nkey2: key2",
match;
while ((match = regex.exec(str)))
{
console.log(match.groups["first"], match.groups["second"]);
console.log(match[1], match[2]);
}
“regex” holds an augmented RegExp instance then, whose inherited exec()
method has been overridden in the instance to return an augmented array-like
object if necessary (otherwise just the inherited method is called, and its
return value returned):
/**
* @function
*/
exec: (function () {
var rx2;
/**
* @param {string} s
* @param {jsx.regexp.RegExp} rx
* Instance to be tested
* @return {boolean}
* <code>true</code> if <var>rx</var> has been constructed
* using this constructor, <code>false</code> otherwise.
*/
function _exec (s, rx)
{
/* NOTE: Use passed expression only when called statically */
if (_getClass(this) == "RegExp")
{
rx = this;
}
rx._realExec = (rx._oldExec || rx.exec);
var matches = rx._realExec(s);
if (matches && _RegExp2.isInstance(rx))
{
matches.groups = _getDataObject();
if (rx.unicodeMode && !rx2)
{
rx2 = new _RegExp2("^\\W+", "u");
}
for (var i = 0, len = matches.length; i < len; ++i)
{
/* Trim leading \b matches */
var patternGroup = rx._patternGroups[i];
if (rx.unicodeMode
&& patternGroup
&& patternGroup.match(
/^(\((\?P?(<([^>]+)>|'([^']+)'))?)*\\b/))
{
matches[i] = matches[i].replace(rx2, "");
}
matches.groups[rx.groups[i] || i] = matches[i];
}
}
return matches;
}
return _exec;
}()),
See <http://PointedEars.de/scripts/test/regexp> for more.
--
PointedEars
Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.
Back to comp.lang.javascript | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Recommendation for new RegExp (Array-extra-like) methods brettz9@gmail.com - 2013-08-28 07:51 -0700
Re: Recommendation for new RegExp (Array-extra-like) methods Andreas Bergmaier <andber93@web.de> - 2013-08-28 17:16 +0200
Re: Recommendation for new RegExp (Array-extra-like) methods brettz9@gmail.com - 2013-08-28 08:21 -0700
Recommendation for array-like methods on Iterator; Was Re: Recommendation for new RegExp (Array-extra-like) methods brettz9@gmail.com - 2013-08-28 16:30 -0700
Re: Recommendation for new RegExp (Array-extra-like) methods Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-08-30 16:00 +0200
Re: Recommendation for new RegExp (Array-extra-like) methods Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-09-01 15:25 +0200
csiph-web