Optional argument types

Dmitry Soshnikov dmitry.soshnikov at gmail.com
Tue Sep 25 11:37:51 PDT 2012


On Tue, Sep 25, 2012 at 11:18 AM, Oliver Hunt <oliver at apple.com> 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 <dmitry.soshnikov at gmail.com>
> wrote:
>
> On Tue, Sep 25, 2012 at 7:37 AM, Andreas Rossberg <rossberg at google.com>wrote:
>
>> On 25 September 2012 15:31, Andrea Giammarchi
>> <andrea.giammarchi at gmail.com> 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
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120925/22be59e6/attachment.html>


More information about the es-discuss mailing list