String finality (was: Re: ARGUMENTS.SHOULD.BE.ARRAY bug-fix)
On Mar 19, 2007, at 1:49 PM, Brendan Eich wrote:
On Mar 19, 2007, at 1:01 PM, zwetan wrote:
but still out of curiosity, in a case where someone would want to do the same kind of methods delegation but with non-generic methods (this value required to be of the original type) does ES4 offers some way of doing it ?
Bound methods cannot be called on a |this| parameter of the wrong type -- they carry their |this| around once extracted (e.g. from a class instance).
I should have distinguished the case of an instance-bound method,
where |this| carried along by the method closure, from a type-
constrained |this| method, where you could extract and call on a
different instance, but the type would still be constrained to be a
subtype of the type from which you extracted the method.
We allow both cases to be expressed. To see both instance-bound and
type-constrained |this| methods, consider this class:
class C { public var x; function C(x) : x = x { }
// An instance-bound class method -- a "fixture" // (DontEnum/DontDelete/ReadOnly and type-constrained // by its function type). function m() { return x; }
// An unbound prototype method with type-constrained |this|. prototype function p(this: {x:*}) { return this.x; } };
let c = new C(42); let m = c.m; print(m()); // prints 42
print(c.p()); // prints 42 also
let o = {m: m, x:43}; print(o.m()); // prints 42 still
o.m = c.p; print(o.m()); // prints 43
So class instance methods are instance-this-bound. Prototype methods
(among other features) are unbound and by default their |this|
parameter is not type-constrained. But you can write (this:T at the
start of a formal parameter list or function type signature to
constrain the type of |this|.
On Mar 19, 2007, at 1:01 PM, zwetan wrote:
Bound methods cannot be called on a |this| parameter of the wrong
type -- they carry their |this| around once extracted (e.g. from a
class instance).
You can't do this today, and it won't work in ES4.
But String's methods are all generic, except for toString and
valueOf, so you could reuse String's generic methods in several ways
(by extracting references to them or their static counterparts; by
subclassing String -- see below; by one-off delegations via .apply or
equivalent).
String is final in AS3, but not final in proposed ES4 as of the last
face-to-face meeting.
Here is the latest plan of record for primitive (string) vs. wrapper
(String) types:
and model wrapping as follows:
intrinsic only, not prototype.
prototype [at the time this was written, intrinsic => final -- we are
revisiting, but backward compatibility does not require intrinsic
methods in String. /be]. * Thus we split intrinsic functionality from String and push it
down into string. * “hi”.charAt(0) therefore invokes String.prototype.charAt on
the string “hi” in the absence of a 'use namespace intrinsic'. * If you want speed and not AOP, 'use namespace intrinsic' or
call “hi”.intrinsic::charAt(0) (or in this case, use indexing). * To support “hi”.nosuch === undefined and “hi”.foo = 42 where a
subsequent "hi".foo results in undefined, we use Jeff’s catchalls
suggestion [defining get *() {...} and set *() {...} on class
string], which simulates ES1-3’s wrapping under ToObject * Code may freely use string and unless it explicitly uses
intrinsic, AOP via String.prototype still works. * And (thanks to the catchalls) generic get-and-test-against- undefined (or equivalent) and useless sets still work.
This applies to boolean/Boolean too. Number is different, given the
several primitive types (int, uint, double, decimal). I'll defer
getting into Number and let people digest the above.