On Jun 13, 2015, at 1:18 PM, C. Scott Ananian wrote:
> To throw some more paint on the bikeshed:
>
> The "instanceof RegExp" and "RegExp(...)" parts of the "perfect"
> implementation of `RegExp.tag` should also be fixed to play nicely with
> species.
>
> I think Allen and I would say that you should *not* use the species pattern
> for instantiating the new regexp (because this is a factory), but you should
> be doing `new this(...)` to create the result, instead of `RegExp(...)`.
> (Domenic might disagree, but this is the pattern the ES6 spec is currently
> consistent with.)
Absolute, `new this(...)` is a pattern that everyone who whats to create
inheritable "static" factory methods needs to learn. It's how such a factory
says: I need to create an instance of the constructor I was invoked upon.
`species` is very different. It is how an instance method says: I need to
create an new instance that is similar to this instance, but lack its
specialized behavior.
>
> The `instanceof RegExp` test might also be reviewed. It might be okay, but
> perhaps you want to invoke a `toRegExp` method instead, or just look at
> `source`, so that we used duck typing instead of a fixed inheritance chain.
> You could even define `String#toRegExp` and have that handle proper escaping.
> This pattern might not play as nicely with subtyping, though, so perhaps
> using `this.escape(string)` (returning an instance of `this`) is in fact
> preferable. Everything other than a string might be passed through `new
> this(somethingelse).source` which could cast it from a "base RegExp" to a
> subclass as necessary. You could handle whatever conversions are necessary in
> the constructor for your subclass.
Originally, ES6 had a @@isRegExp property that was used to brand objects that
could be used in context's where RegExp instances were expected. It was used by
methods like String.prototype.match/split/search/replace to determine if the
"pattern" argument was an "regular expression" rather than a string. Latter
@@isRegExp was eliminated and replaced with @@match, @@search, @@split, and
@@replace because we realized that the corresponding methods didn't depend upon
the full generality of regular expressions, but only upon the more specific
behaviors. When we did that, we also decided that we would use the present of
@@match a property as the brand to identify regular expression like objects.
This is captured in the ES6 spec. by the IsRegExp abstract operation
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-isregexp which is used
at several places within the ES6 spec.
So, the property ES6 way to do a cross-realm friendly check for RegExp like
behavior is to check for the existence of a property whose key is Symbol.match
>
> If we did want to use the species pattern, the best way (IMO) would be to
> expose the fundamental alternation/concatenation/etc operators. For example,
> `RegExp.prototype.concat(x)` would use the species pattern to produce a
> result, and would also handle escaping `x` if it was a string. The set of
> instance methods needed is large but not *too* large: `concat`, `alt`,
> `mult`, and `group` (with options) might be sufficient.
yes.
Again, the key difference is whether we are talking about a request to a
constructor object or a request to an instance object.
MyArraySubclass.of(1,2,3,4) //I expect to get an instance of
MyArraySubclass, not of Array or some other Array-like species
aMyArraySubclassObject.map(from=>f(from)) //I expect to get something with
Array behavior but it may not be an instance of MyArraySubclass
Allen
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss