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