Type Parameters are Completely Unnecessary
On Mar 4, 2008, at 10:27 PM, Darryl wrote:
I would argue that type parameters for collection classes are completely unnecessary. Supposing some collection class Set with a method add, it would be trivial to subclass it to TypedSet. Simply have an argument in the constructor called contentType, and redefine add to force type checking of all items being added, filtering out anything not matching. I don't see why it's necessary to clutter up the syntax with ugly Set.<int> like notation when existing functionality can handle this sort of type constraints with ease and elegance.
Arguments to a constructor can't be type terms, so can't be used in
annotations, so can't be type-checked. You must mean manual, runtime
"type" checking by typeof, instanceof, or other tests. That's not
what type checking means in the context of type parameters.
I suggest focusing on semantics and setting aside syntactic issues
for a bit. If you just don't want optional types anywhere, then why
pick on type params?
*Note: whoops, I accidental replied to sender not to the list. Sorry.
<< Arguments to a constructor can't be type terms, so can't be used in annotations, so can't be type-checked. You must mean manual, runtime "type" checking by typeof, instanceof, or other tests. That's not what type checking means in the context of type parameters. >>
I understand that it's different than run-time type checking, but the question is the necessity of this sort of thing as a feature of syntax.
<< I suggest focusing on semantics and setting aside
syntactic issues
for a bit. If you just don't want optional types
anywhere, then why
pick on type params? >>
Optional types are fine, but I think including something in syntax should only occur if it's necessary, and I don't see it as being necessary given the fact that type checking exists within the language. Given that things like strings and arrays and such are all classes, passing that is what I had in mind. For instance, off the top of my head,
var numberSet = new TypedSet(Number);
which has an add method like
function(obj){ if( obj instanceof Number ){ //add it } }
As it is, I find
var numberSet = new Set.<Number>();
to be incredibly ugly and I'm one of those Code Should Be Beautiful sorts, so this is a huge problem for me. I'd go so far as to say that because "types" are classes (afaik), there should be absolutely no reason you can't refer to types.
--Added--
Also, consider this: Suppose I want a set that EXCLUDES a certain type? Do we need special syntax for this too? <!type> maybe? If it were just a parameter,
then a coy little generic "not" function could exist that wraps a class in an object, like say Not(Number) = { kind: "not", value: Number }, as in TypedSet(Not(Number)), so that add can now see that the class is wrapped in a not that excludes it, rather than requires it. This is a trivial thing to do if your set-content-type is defined through existing methods, but becomes tricky if you have to do special syntax for it.
And then I might go on to say, well why not just have syntax for this and syntax for that and lets put everything in syntax and nevermind actually using the language to build stuff the language should be that stuff. My contention is that you don't NEED typed parameters, they don't add much utility and certain detract from aesthetics, and they aren't really core conceptual features of what these classes are, they're extensions on the notion of what they do.
o/// Be seeing you...
____________________________________________________________________________________
Never miss a thing. Make Yahoo your home page. www.yahoo.com/r/hs
[Resending my private-in-turn reply, edited a bit. /be]
On Mar 4, 2008, at 10:48 PM, Darryl wrote:
var numberSet = new TypedSet(Number);
I wanted to point out how we considered making type parameters be
ordinary call parameters, see:
proposals:type_parameters, discussion:type_parameters
The latter includes an attempt by Jeff Dyer (look for — Jeff Dyer
2006/02/27 14:55) to use a parenthesized parameter list. Then came
doku.php? id=discussion:type_parameters#the_bracket_issue
There was a belief that we could parameterize Array by type, but in
ES1-3 it already can be called as a function taking parameters, so
that hope died. It may have distorted our wish to use a distinct
bracketed type parameter list, but not much: the problem remains that
in order to have a strict mode, we need type terms to be constants,
and in order to keep implementations "small", we do not want any
fancy analyses to be required.
You can read the rest of the discussion if you have time to kill, but
the gist of it is that distinct brackets for type parameter lists are
necessary, the C++, Java, or C# syntax of Vector<double> is hard
enough to parse that we passed on it, and after struggling to find
other bracket chars, we ended up using an unambiguous syntactic
extension: Vector.<double>.
Again, if you believe that all type checking should be written out as
code, then you don't want type parameters. But you don't want types,
period, so best to argue that case instead of singling out type
parameters.
which has an add method like
function(obj){ if( obj instanceof Number ){ //add it } }
That's not type-checking in the optional types sense. It's tedious
and error-prone, and hard enough that people tend not to write such
code, instead using duck typing in a more "if it doesn't quack like a
duck, step on it!" way.
Type parameters follow naturally from wanting types to be first class
runtime terms, not just values that have to be checked manually.
As it is, I find
var numberSet = new Set.<Number>();
to be incredibly ugly
I guess my plea to put aside syntax and aesthetics didn't work.
You're being blinded to the meaning, which is where the motivation
arises.
Would you prefer Set<Number> a la C++, Java, and C#?
I'd go so far as to say that because "types" are classes (afaik), there should be absolutely no reason you can't refer to types.
Types are not all classes. There are structural types (even today,
latent in ES3: functions are structural, not nominal). Have you read
the overview doc at ecmascript.org yet?
<< Notice now that you can't check anything about the
type passed to
TypedSet. For example, you can't check (at runtime, or
using the
optional strict mode, doesn't matter) that Number is a
subtype of
some other type. Also, the implementation can't
optimize, e.g.
Vector.<double> into packed double[] storage. >>
Then I would argue that the implementation is flawed. Implementation should not factor into language design. If it did, we'd end up with having JS be just C with the dangerous stuff cut out, and then compiled on the fly, because surely that would be simpler than designing a whole new language, but that's an absurd prospect. Make the language do what you want it to do elegantly and simply, and then figure out how to make it work. This "solution" seems more like you said, "Oh, crap, how can we put this into syntax given how we're implementing JS?" and that to me is completely backwards in terms of language design.
<< That's not type-checking in the optional types
sense. It's tedious
and error-prone, and hard enough that people tend not
to write such
code, instead using duck typing in a more "if it
doesn't quack like a
duck, step on it!" way.
Type parameters follow naturally from wanting types to
be first class
runtime terms, not just values that have to be checked
manually. >>
I'm not saying it's an ideal way of doing things, maybe you could do something like
Class TypedSet(contentType){
function add(obj:contentType){
...
}
}
Oh sure, JS2 as-is might not be able to cope with this, but there's no reason at all why you couldn't make it cope. And that's the point. This is a trivial difference, no change in syntax just in how you can use things. It's purely a semantic difference, but it's immensely more elegant and understandable.
<< I guess my plea to put aside syntax and aesthetics
didn't work.
You're being blinded to the meaning, which is where
the motivation
arises.
Would you prefer Set<Number> a la C++, Java, and C#?
Syntax and aesthetics are incredibly important, tho, in conveying meaning. If meaning is all you care about then why not use some incomprehensible way of representing type restrictions? Because languages need to be usable and elegant to be good languages, not merely capable of doing something. I don't want Set<Number> either (tho seriously, why would you add a
dot that conveys absolutely nothing and complicates the notion of what dots do?), I would prefer something more consistent with the notion of what JavaScript is.
<< Types are not all classes. There are structural
types (even today,
latent in ES3: functions are structural, not nominal).
Maybe they should all be classes. Plus, I don't see why it should matter what ES3 does. This is ES4, not ES3. I understand the desire to be somewhat backwards compatible, but letting that hamper the language is foolish. Sometimes you just have to say, "This is completely new, but it's better because of that."
<< Have you read the overview doc at ecmascript.org yet? >>
Oh I've tried, but it's not the most user friendly website out there.
Listen, I understand that this isn't going to change your mind about the issue, because you're well on your way to making this thing finished. You've said many times before that the spec has been finalized. But it's worth pointing out that the language is still designed in less than ideal ways. It's only by virtue of the fact that JavaScript is the only language natively executable by web browsers that makes this sort of thing even remotely possible. If multiple languages were available I think you'd end up worrying that JavaScript might go out of fashion like Fortran regardless of what it can do.
o/// Be seeing you...
____________________________________________________________________________________
Never miss a thing. Make Yahoo your home page. www.yahoo.com/r/hs
<< The benefits of a compile-time check over a runtime check include performance and type safety. >>
As a JS programmer I can't see any way in which you can compile-time check anything other than a static collection, and thus I can't see how this would be of any benefit at all performance wise. As for type safety, that's an implementation problem afaic, not a design problem. As a programmer, I don't care how you get it to be type safe, I care about how good the language is to code in, and Set.<Number> is the kind
of thing that's going to make the language unappealing to me. The only reason I don't switch is because, well, what to? JS has a monopoly on in-browser language.
o/// Be seeing you...
____________________________________________________________________________________
Looking for last minute shopping deals?
Find them fast with Yahoo! Search. tools.search.yahoo.com/newsearch/category.php?category=shopping
On Mar 4, 2008, at 11:24 PM, Darryl wrote:
<< The benefits of a compile-time check over a runtime check include performance and type safety. >>
As a JS programmer I can't see any way in which you can compile-time check anything other than a static collection,
Strict mode is optional for development time, not for deployed code.
Unlike static languages, strict mode has loopholes, so you don't need
to type everything to get benefits from the static checking.
and thus I can't see how this would be of any benefit at all performance wise.
Who said anything about performance?
Not I; I've said before that types have little to do with
performance, although straightforward use of types and early binding
can help some implementations go fast. Performance through (optional)
static types has never been the motivating reason for ES4's type system.
As for type safety, that's an implementation problem afaic, not a design problem.
This is clearly false. Type safety depends on specified language
design (e.g. covariant argument subtyping in early Eiffel), not on
implementation. But I am not sure we are speaking the same language,
so I'll stop here.
On Mar 4, 2008, at 11:20 PM, Darryl wrote:
I'm not saying it's an ideal way of doing things, maybe you could do something like
Class TypedSet(contentType){
function add(obj:contentType){ ... }
}
Oh sure, JS2 as-is might not be able to cope with this, but there's no reason at all why you couldn't make it cope.
Please read the links I sent in the public reply to your message,
originally sent only to me. We considered exactly syntax like what
you show above, but we rejected it, since we want a deterministic
type system that supports both (a) optional and (b) cheap-enough-to-
be-practical static checking.
<< Have you read the overview doc at ecmascript.org yet? >>
Oh I've tried, but it's not the most user friendly website out there.
I meant this document:
www.ecmascript.org/es4/spec/overview.pdf
It's linked from the front page with "overview" in the link text.
Listen, I understand that this isn't going to change your mind about the issue, because you're well on your way to making this thing finished.
We can change syntax (do you have an alternative syntax?), but if you
can't see beyond it, or grapple with the semantic reasons for
distinguishing type parameters from ordinary call parameters, we are
not going to get anywhere.
You've said many times before that the spec has been finalized.
No, I've never said that. We're obviously not done because there is
no consolidated spec, even a draft spec, for the whole language. My
post here:
mail.mozilla.org/pipermail/es4-discuss/2008-February/001927.html
says explicitly that we don't yet have a finalized spec.
But it's worth pointing out that the language is still designed in less than ideal ways. It's only by virtue of the fact that JavaScript is the only language natively executable by web browsers that makes this sort of thing even remotely possible. If multiple languages were available I think you'd end up worrying that JavaScript might go out of fashion like Fortran regardless of what it can do.
I doubt it, since I've worked to get other languages supported in
Mozilla, and on Tamarin.
At this point, you're not arguing rationally and veering toward
personal attack, so I'll stop trying to respond with rational argument.
Brendan Eich said:
<< This is clearly false. Type safety depends on
specified language
design (e.g. covariant argument subtyping in early
Eiffel), not on
implementation. But I am not sure we are speaking the
same language,
so I'll stop here. >>
Ofcourse you have languages that mix the two. But as a programmer I don't care about how you achieve it, and hence I don't think that it should impact syntax. The two should be separate. If you want to do compile-time stuff to maintain type safety, go right ahead, but I don't see any reason why I should have to concern myself with this distinction.
o/// Be seeing you...
____________________________________________________________________________________
Looking for last minute shopping deals?
Find them fast with Yahoo! Search. tools.search.yahoo.com/newsearch/category.php?category=shopping
I apologize if it sounds like I'm attacking you personally, that's not my intention.
I merely mean to convey that I think what this syntax is doing is enforcing in syntax a notion related to implementation, and I don't think that this is something that should be done.
o/// Be seeing you...
____________________________________________________________________________________
Never miss a thing. Make Yahoo your home page. www.yahoo.com/r/hs
Last reply from me, this message veered away from personal attack --
for that, thanks.
On Mar 4, 2008, at 11:42 PM, Darryl wrote:
Brendan Eich said:
<< This is clearly false. Type safety depends on specified language design (e.g. covariant argument subtyping in early Eiffel), not on implementation. But I am not sure we are speaking the same language, so I'll stop here. >>
Ofcourse you have languages that mix the two. But as a programmer I don't care about how you achieve it, and hence I don't think that it should impact syntax. The two should be separate. If you want to do compile-time stuff to maintain type safety, go right ahead, but I don't see any reason why I should have to concern myself with this distinction.
The design is important, because without distinguished type
parameters, programmers may not know the meaning of C(T) -- is it a
call, or a parameterized type instantiation? This has nothing to do
with implementation issues.
Also, if you give up making type terms (in annotations and actual
type parameter lists, among other places) constants, then the type
checker may not be deterministic. If you make restrictions to gain
back determinism, the system may still have bad time complexity. Such
a type system can be and has been implemented, but it can take lots
of code, and it can run in exponential time. A standard way to cope
with the possibility of divergence is to set a watchdog timer.
This is not the optional strict mode users want.
If you make type terms purely runtime, and throw out strict mode
altogether, then what you propose (all in the name of syntax) can be
implemented. It's like the contract systems from PLT Scheme and other
such systems. We've considered it -- see the wiki.
But the benefit of strict mode is for finding bugs before code runs.
It's designed that way. Strict mode is not related to implementation
properties to do with performance.
So the design of type parameters is really is about language design,
not implementation. That should be obvious from the wiki pages I
linked to.
On Mar 4, 2008, at 11:56 PM, Brendan Eich wrote:
So the design of type parameters is really is about language design, not implementation. That should be obvious from the wiki pages I linked to.
Obviously design takes into account many things, including
implementation feasibility and costs. I'm probably gilding the lily
here, but my point was that type parameters need to be constrained
for programmer usability and a practical strict mode, never mind
runtime implementation issues.
Perhaps you could provide an example of a situation in which this sort of type parameter on collections is beneficial. I can't picture a situation in which, given what you've said, this could be at all useful, and that might be why I fail to see the point of doing it this way.
o/// Be seeing you...
____________________________________________________________________________________
Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now. mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ
On Mar 5, 2008, at 12:27 AM, Darryl wrote:
Perhaps you could provide an example of a situation in which this sort of type parameter on collections is beneficial. I can't picture a situation in which, given what you've said, this could be at all useful, and that might be why I fail to see the point of doing it this way.
Sure. Here's ES4 Map as proposed:
ES4 dynamic class Map.<K,V> { public function Map(equals: function = (function(a,b) a === b), hashcode: function = intrinsic::hashcode) …
static meta function invoke(object: Object): Map.<EnumerableId,*> …
static public const length = 2;
intrinsic function size() : uint …
intrinsic function get(key: K, notfound: (V|undefined)
=undefined) : (V|undefined) … intrinsic function put(key: K, value: V, notfound: (V|undefined) =undefined) : (V|undefined) … intrinsic function has(key:K) : boolean … intrinsic function remove(key:K) : boolean … intrinsic function clear() : void …
iterator function get(deep: boolean = false) :
iterator::IteratorType.<K> …
iterator function getKeys(deep: boolean = false) :
iterator::IteratorType.<K> …
iterator function getValues(deep: boolean = false) :
iterator::IteratorType.<V> …
iterator function getItems(deep: boolean = false) :
iterator::IteratorType.<[K,V]> …
private const equals : function = …
private const hashcode : function = …
private var population : uint = …
}
By convention the type parameter names are short, all-caps. A couple
of points:
- The type parameter list .<K,V> makes it clear that class Map is
generic, you have to intantiate it with type arguments before you can
call its constructor with equals and hashcode function arguments.
- The type parameters and annotations that use them make evaluation
in either standard or strict mode straightforward for users to reason
about. Readers can see that K means the same thing everywhere, they
do not have to read verbose, runtime-type-checking code in each method.
How would you rewrite this class to avoid the syntax you don't like?
You don't have to preserve constant type terms. Use ES3 if you like.
I would argue that type parameters for collection classes are completely unnecessary. Supposing some collection class Set with a method add, it would be trivial to subclass it to TypedSet. Simply have an argument in the constructor called contentType, and redefine add to force type checking of all items being added, filtering out anything not matching. I don't see why it's necessary to clutter up the syntax with ugly Set.<int> like notation when existing
functionality can handle this sort of type constraints with ease and elegance.
o/// Be seeing you...
Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now. mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ