Prev: Putting passwords in a properties file?
Next: Interview
From: Kenneth P. Turvey on 4 Oct 2009 02:06 On Sat, 03 Oct 2009 17:12:18 -0700, Roedy Green wrote: [Snip] > Generics lack the elegance of other Java features. The syntax is ad hoc, > unshaved, irregular, Perlish, unfinished. [Snip] I find them more useful than you seem to, but your right about the syntax. It is quite, quite ugly. -- Kenneth P. Turvey <evoturvey(a)gmail.com>
From: Kenneth P. Turvey on 4 Oct 2009 02:12 On Sat, 03 Oct 2009 21:34:46 -0400, Joshua Cranmer wrote: [Snip] > > How was that? Very good... and yet most developers will need to read it more than once. -- Kenneth P. Turvey <evoturvey(a)gmail.com>
From: Lew on 4 Oct 2009 10:09 Kenneth P. Turvey wrote: > On Sat, 03 Oct 2009 17:12:18 -0700, Roedy Green wrote: > > [Snip] >> Generics lack the elegance of other Java features. The syntax is ad hoc, >> unshaved, irregular, Perlish, unfinished. > [Snip] > > I find them more useful than you seem to, but your right about the > syntax. It is quite, quite ugly. If by "ugly" you mean "elegant, useful and expressive", then I agree. -- Lew
From: Joshua Cranmer on 4 Oct 2009 13:19 On 10/04/2009 02:06 AM, Kenneth P. Turvey wrote: > On Sat, 03 Oct 2009 17:12:18 -0700, Roedy Green wrote: > > [Snip] >> Generics lack the elegance of other Java features. The syntax is ad hoc, >> unshaved, irregular, Perlish, unfinished. > [Snip] > > I find them more useful than you seem to, but your right about the > syntax. It is quite, quite ugly. What syntax would you use then? If you go for something that distinguishes between left and right delimiters, you have just four choices: (), [], {}, and <> [1]. {} denotes a block, so it is entirely the wrong thing to use IMHO. () denotes either overriding precedence, a type conversion, or a method call, and I think it is already more than overloaded. If you perhaps want only one token to separate the generics parameter from the rest, you have many more choices. `:', `;', `,', and `.' are untenable for what I hope are obvious reasons. `%', `^', `&', `*', `|', `/', `+', `-', and `=' are all binary operator tokens, which means using them as a delimiter in identifiers is again problematic (think name lookup). `~', `!', `?' are unary (or ternary, in the last case) operators, which eases on the problems of using them as a delimiter token (id <TOK> id is unambiguously the generics invocation), but reusing them would be awkward. That leaves us with `@', `#', and ``' and `\' as possible tokens for unary style (`$' and `_' are both valid in identifier names). We can therefore reduce the syntax into one of six possible styles: List[Integer] List<Integer> List(a)Integer List#Integer List`Integer List\Integer The last one has a `\u' problem (it's translated before tokens are read), so that is pretty much out of the question. Using ``' is aesthetically horrendous, if you ask me. Annotations used `@' first; besides, Integer(a)List looks more meaningful anyways (nothing stops one from using it in that format anyways). What List[Integer] has going for it is that the array syntax fits closer into a notation of what a generics type generally does: it's a container of some object. On the other hand, it looks like an array access, which means that the parser would look rather interesting. On the other hand, List#Integer is perhaps the second most appealing of possible unary-style formats (following List$Integer, but that's a valid identifier already!). The pound sign is unused as a token in Java, which means the syntax is wholly unambiguous. Unary tokens have the notable drawback that nested and/or multiple types are hard to write (should A#B#C be A<B, C> or A<B<C>>? or do you do A#B, C?). You can get around this by requiring the end token (e.g., List#Integer#), but then the appeal of the single unary token rapidly vanishes. In the end, the only one that ends up being rather possible is List<Integer>. If you drop the objection to curly braces delimiting blocks, List{Integer} also looks somewhat visually appealing, but I think that so severely overloading the { is out of the question IMHO. FWIW, if you think the generics syntax is bad, look at the BGGA closures proposal. IMO, the single worst part about function pointers is that there is no easy way to write them. Examples: static { => int } answer = { => 42 }; { int => String } toBinary = { int x => Integer.toBinaryString(x) }; { String => int } parseInt = Integer#parseInt(String); { Box => int } getX = Box#getX(); { String => Set<String> } singleton = Collections#<String>singleton(String); static for void eachEntry(int[] values, { int ==> void } block) { for (int p : values) { block.invoke(p); } } [2] And, at one point (I think this part was backed out though), the statement `return 42' meant something completely different from the similar `return 42;'. Yowsers. [1] In principle, you could also include \/ or perhaps /\ in this list, but I'm just going to toss that possibility out from the get-go on the basis that \u causes magic to happen before even the tokenization step, so including that as part of an identifier is not recommended. [2] I noticed as I was getting examples that some closures seemed to use => and others ==>. I think over the course of development, the closures construct was changed to use ==> instead of =>, while the type definition for function pointers remained =>. -- Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald E. Knuth
From: Lew on 4 Oct 2009 13:33
Joshua Cranmer wrote: > What List[Integer] has going for it is that the array syntax fits closer > into a notation of what a generics type generally does: it's a container > of some object. Not necessarily. <http://java.sun.com/javase/6/docs/api/java/util/Comparator.html> Comparator[Number] doesn't seem so sensible to one used to thinking of [] as an indicator for an array or association. -- Lew |