function f(Boolean b) {
   if (b) ...
}

f(false)

has very different semantics from

function f(b) { if (b) ... }

f(false)

Likewise eliding boxing is very very hard if anything happens to mutate any 
portion of the proto chain for String, etc.

You also run into semantic issue if you do:

Foo = String

function f(Foo h) { .... }

Should this box?  If it should box then what we're saying is that the semantic 
behaviour of

function f(Foo h) 

is

function f(h) {
    if (!Object.isObject(h)) h = new Foo(h)
    if (!(h instanceof Foo)) throw ...;
    ...
}

Which is the horror of C++ implicit constructor conversions

If we say that

Foo = String;
function f(Foo h) ..

is semantically different from

function f(String h)

then we're implying that String has become a context dependent keyword (which 
is what i meant to imply for my prior primitive type names)

--Oliver

On Sep 25, 2012, at 11:37 AM, Dmitry Soshnikov <[email protected]> 
wrote:

> On Tue, Sep 25, 2012 at 11:18 AM, Oliver Hunt <[email protected]> wrote:
> I'm very concerned about the interaction of boxed primitives and these type 
> guards, especially in the context of multiple global objects (i.e. the 
> standard browser environment).
> 
> I'm not sure what the best solution to this is -- the [[NativeBrand]] concept 
> worries me as it hides the potential for different types being passed into an 
> ostensibly singly typed variable.  Likewise I'd be worried about instanceof 
> causing problems for the exact opposite reason (eg. instanceof Array not 
> working across globals).
> 
> I'm not sure what the spec currently says w.r.t implicit boxing off the top 
> of my head, but I would be prefer that implicit boxing would not be allowed.
> 
> Then we could have at least a few primitive types: number, bool[ean], string, 
> function, say.  The primitive names would take precedence over the result of 
> any lookup, and if someone wanted to force a lookup then they could use ""'s. 
>  This also would mean that Number and number as types would be (correctly) 
> distinguished.
> 
> I'm unsure what the default values for a primitive typed variable should be, 
> but I'm generally opposed to TDZs.
> 
> 
> In real practice though, I don't think there can be the cases when "strings" 
> or `new Strings` are worth to distinguish and to work separately in the code 
> (I mean exactly to route the code differently based on it). That's literally 
> -- I cannot imagine any practical example of it (OK, I cannot imaging even a 
> theoretical example of routing the code based on primitive vs. box-values).
> 
> The only thing when "string" vs `new String` arrives is exactly the errors of 
> trying to _test the type_ of passed arguments as:
> 
> if (typeof foo == "string") { ... }
> 
> and then their `new String` doesn't work for them. Then they switch to 
> [[NativeBrand]] checks instead.
> 
> So for `foo(String bar) { ... }` in real practice both, "string" and `new 
> String` should pass I think.
> 
> P.S.: actually, the one theoretical/practical distinguishing example is when 
> a programmer say want to save some state on the passed value, e.g.:
> 
> foo(String bar) {
>   bar.count  = 10;
> }
> 
> It won't work for primitives (since an intermediate wrapper is destroyed 
> after property resolution). But this is kind of the hint for the programmer 
> himself that he should pass then `new String` always there, but not just 
> "strings".
> 
> And foo(String bar) for `new Strings`, and foo(string bar) for "strings" 
> interesting by itself, but introduces new keywords, and also keeps logical 
> separation b/w primitives vs. boxes. In real practice again, programmers 
> don't even think about it in application tasks and if so, try to avoid.
> 
> Dmitry 
> 
>  
> --Oliver
> 
> On Sep 25, 2012, at 10:56 AM, Dmitry Soshnikov <[email protected]> 
> wrote:
> 
>> On Tue, Sep 25, 2012 at 7:37 AM, Andreas Rossberg <[email protected]> 
>> wrote:
>> On 25 September 2012 15:31, Andrea Giammarchi
>> <[email protected]> wrote:
>> > That's a hell of a question ... shapes speaking I'd say structural, since
>> > AFAIK shapes are those boosted up more, isn't it?
>> >
>> > That would solve String VS string and Array VS Arguments which is, I
>> > believe, kinda desired.
>> >
>> > Which one would you chose ?
>> 
>> I assume that most people would probably prefer structural types in
>> principle, but the problem is that they induce far, far more expensive
>> runtime checking (easily an order of magnitude). Which is why guards
>> and trademarks were proposed as a more conservative, nominal
>> mechanism.
>> 
>> Generally speaking, retrofitting something type-like on an untyped
>> language is a *very* hard problem. It has been tried with many
>> languages and has succeeded for very, very few. You can read lots and
>> lots of research papers on the subject.
>> 
>> Fortunately, though, we have top-notch expertise on that topic on
>> TC39, e.g. Sam TH. ;)
>> 
>> I believe all this is true, and this is why I underlined in the first letter 
>> that it's kind of not a "type system" by itself, but only the runtime (yes, 
>> runtime) check of the "type-tags" of the argument values. And only the 
>> argument values.
>>  
>> That's said, introducing the types for casual vars, like:
>> 
>> let x :: Number = 10;
>> 
>> pushes the responsibility of type carrying to the variable. Thus changing 
>> the semantics of the environments model, where the vars don't carry the 
>> type, but just reference to the values which carry the type. The line above, 
>> if to accept such a "type system" would look like x = "foo" is the error 
>> then.
>> 
>> Having this "type hints" only for arguments, reduces the problem only for 
>> checking the "type-tags" of the arguments, in the function's prologue. And 
>> it can be done only in runtime (a function can be applied in different ways, 
>> and it's not possible to determined lexically with what "types" of 
>> arguments, so only the runtime).
>> 
>> By "type-tags" I mean a generic way of testing. Not the `typeof` result, not 
>> the `instanceof`. But e.g. the [[NativeBrand]] (for natives) + `instanceof` 
>> for custom constructors (the later is just an extension).
>> 
>> This gives the ability not to think about it as a "type system", but just as 
>> "type hints for arguments". Because again, after the arguments have been 
>> checked for the "type-tag" at activation, the argument vars themselves can 
>> be rebound to the values of different types, underlining that the variable 
>> are not related with the types, and the type annotations for function 
>> arguments are just type annotations for checking the types of passed values 
>> at only activation.
>> 
>> This is kind of scheme I have in mind. I understand all the consequences of 
>> (not)optimizations and runtime coasts, but if devs are need these type 
>> checks, then they do this anyway manually (and usually in the prologue of 
>> the functions) at runtime today. So providing this would make it just 
>> implicit. Still with understanding that this is a runtime check, which may 
>> decrease the speed of function execution -- but it's already decreased once 
>> they do this manually anyway.
>> 
>> This model btw is used in PHP as well (type hints only for function 
>> arguments, but any var can be reassigned to the value of different type, 
>> underlining that this not a "type system").
>> 
>> Today's check to which we can compile our sources with a build-tool is:
>> 
>> function foo(String bar, Widget baz) { ... }
>> 
>> is:
>> 
>> if (bar.[[NativeBrand]] != "String") throw TypeError(...);
>> if (!(baz instanceof Widget)) throw TypeError(...);
>> 
>> (it's easy to distinguish which type-tag, either [[NativeBrand]] or the 
>> instanceof, to use in order to check which value, natives are known, and all 
>> others may be checked with the instanceof). Thus, the later is just an 
>> extension, we can check only for natives, not bothering with 
>> constructors/classes. 
>> 
>> Anyways, since it's hard to implement it now and since it may coast too much 
>> in respect of VMs optimizations, I think any big project may solve this 
>> problem with own implementations with pre-processors/compilers. Thus, some 
>> exact syntactic form (if it will be widely adopted by some big community) 
>> can be then reused for standardization.
>> 
>> P.S.: and to think about type-system in JS is hard, since it doesn't have 
>> it. It has just a mess with `typeof` vs. `instanceof` vs. [[NativeBrand]] 
>> vs. "ducks" (aka "[[NativeBrand]]-like objects"). And therefore, again, 
>> those "type-hints" for args are not about a "type-system".
>> 
>> Dmitry
>> _______________________________________________
>> es-discuss mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/es-discuss
> 
> 

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to