> On Oct 21, 2007, at 11:48 AM, Jeff Dyer wrote:
>>> The wrapper classes String, Number, Boolean are similar to the
>>> (primitive) values they wrap, but they're not really related to
>>> value types in a type sense, and in ES4 the wrappers are of even
>>> utility than in ES3, I would say.
>> Right, thanks for the correction. This is an obvious consequence of
>> recent return of primitive wrappers to ES4. 'string' is the new
> String has its uses, not just embedded in content that requires
> compatibility: string and String inter-convert, String is non-final,
> and the two share a prototype object.
> The need for string comes directly from ES1-3, because the primitive
> string type in JS1 was auto-wrapped when you used a string value as
> if it were an object, say to call a method on it. But since a new
> wrapper was created each time (or so it appeared; implementations
> could optimize), the object-ness of the primitive string was
> ephemeral: you couldn't set methods and get them later; any get on
> the wrapper for a property not found on String.prototype or above
> would return undefined.
> In ES4, string has catchalls to satisfy this ephemeral wrapper get/
> set compatibility, but method calls on string instances do not
> require String wrapper creation.
Are you saying for compatibility you have to maintain this 'ephemeral
> Wrapper creation may or may not be observable in ES3 -- 9.9 says
> "create a new String" but does not say by evaluating |String| in
> order to construct -- but ES4 does not allow any type name to be re-
> bound, so the implementations that chose to construct the wrapper by
> reflecting on the current value of 'String' in the global object,
> thereby allowing someone to replace that binding and spy on wrapper
> construction, no longer need to reflect each time.
> The shared prototype object allows for replacement of prototype
> methods, which per ES1-3 and much compatibility-constraining content
> on the web, remain mutably bound in the shared prototype object. Thus
> in ES1-3, if you wrapped String.prototype.charAt with some AOP advice
> function, your code calling "hi".charAt(0) will still run your advice.
> Since ("hi instanceof String) was never true, it should not be true
> in the new world. This is one reason string and String are peer
> subtypes of Object, that is, string is not a subtype of String.
IWBNI there were a single test for string-ness. In ES3, you have to
typeof x == 'string' || (typeof x == 'object && x instanceof String)
Am I right in thinking that in ES4 you will be able to say:
x is string
to ask the same question?
> Tucker and others have hoped for a way to customize String, and since
> it is non-final and convertible to string, the use-cases that want to
> make custom objects that delegate to String.prototype should work
> too. But it would be good to see some examples.
> IWBNI there were a single test for string-ness. In ES3, you have to
> typeof x == 'string' || (typeof x == 'object && x instanceof String)
> Am I right in thinking that in ES4 you will be able to say:
> x is string
> to ask the same question?
x is AnyString
instead. AnyString is a predefined union type containing String and
string. (Ditto AnyBoolean, AnyNumber.)
On Oct 22, 2007, at 4:53 AM, P T Withington wrote:
>> String has its uses, not just embedded in content that requires
>> compatibility: string and String inter-convert, String is non-final,
>> and the two share a prototype object.
> I think Dylan would have made String an open subclass of the sealed
> class string: http://www.opendylan.org/books/dpg/db_305.html
We can have dynamic subclasses of non-dynamic classes, but if String
<: string, then string can't be final, which precludes some
optimizations and (separate) simplifications. We think these matter
enough not to make String <: string.
Such a relation would also be "upside down" by comparison to ES1-3,
where the primitive string type is not an object type, and even if
you pretended it were, it would not be superior to, or more general
than, String (in any prototype-based or class-based sense). Exactly
the opposite is true: String is more general than string.
>> In ES4, string has catchalls to satisfy this ephemeral wrapper get/
>> set compatibility, but method calls on string instances do not
>> require String wrapper creation.
> Are you saying for compatibility you have to maintain this 'ephemeral
> wrapper' behavior?
Yes. The use-case is generic programming over string primitives and
bona-fide ES3 objects: you want to allow "hello" to flow into a
function farble(x) that gets and/or sets ad-hoc properties on x,
without exceptions being thrown. Such a function can't count on
getting what it set, of course (ephemeral wrappers). But it must fail
soft as it has for going on 12 years.
> My use case is for an annotated string, the result of a sprintf-like
> formatter that remembers the objects associated with each
> representation (so you can inspect a message for more detailed
> information): http://svn.openlaszlo.org/openlaszlo/trunk/WEB-INF/lps/ > lfc/debugger/LzMessage.lzs
Looks like it should derive from String and be happy in ES4. I'll
take a closer look later today.