In what way is your:

TYPE Point3D = ARRAY 3 OF REAL;

any different from my hypothetical:

typedef StringList extends List of String;

 - because, as I mentioned, either of those are either (A) still
structural typing, if "TYPE Floobargle = ARRAY 3 of REAL;" is
interchangible with a Point3D, or (B) a fundamentally different
concept, if they aren't interchangible, and roughly equivalent to:
public class StringList extends List, with some minor syntax sugar
thrown in to tighten type limits.

As my original post hints at, almost all languages are hybrid if only
you theorize long enough. So, instead of getting boiled down in a
purely pedantic waste of time, I'll rephrase to:

Java with BGGA would move java quite a ways towards the left on the
Structural <-> Nominal typing axis. This is a major change, which has
a great impact on the feel of java, and it is not necessary for a
closure proposal, even one that supports full transparency.


Can we all agree on that, instead?


NB: A closure proposal with transparency and without structural types
works roughly like this:

(1) Closure literals are legal only in an environment with an obvious
and unambiguous target type. In other words, you can only pass them
verbatim as a method parameter, or as the expression of an assignment
operation. This is in practice not a big loss; hierarchical closure
types don't have much use (e.g. where I implement, say, a
"FooBarListenerChild" instead of a "FooBarListener" - it's kind of
hard to even imagine what that means, and doing direct operations on a
closure that you just defined is similarly pointless (what are you
going to do, call the apply function on it? Then you could have just
written the code verbatim. You create closures so you can hand them
off or store them).

(2) Via target typing, you always know exactly what kind of nominal
type the closure was meant to become. Thus, something like:

Collections.sort(someStringList, #(String a, String b) {
    inner.return Integer.valueOf(a.length()).compareTo(b.length());
});

would be legal, would be transparent*, and is fully nominally typed;
the compiler will immediately attempt to infer a type on this closure,
which in this scenario is possible, as there's only one matching
method named 'sort' in java.util.Collections that fits the obvious
aspects of this method call (2 arguments, first is a List<String>,
second is a closure taking in parameters 'String, String'). In other
words, this is static, nominal, latent typing, not static, structural
typing. It's also latent/manifest hybrid:

Collections.sort(someStringList, Comparator#(String a, String b) {
    inner.return Integer.valueOf(a.length()).compareTo(b.length());
});

which is not just nice for those who dislike latent typing, but also
serves as an easy mechanism in the face of inference confusion, for
example due to method overloading.

*) "inner.return" is not syntactically transparent, at least not
according to TCP. However, the 'return', 'break', 'continue', and
'throw' statements change meaning depending on their lexical context,
but TCP-style transparency dictates that code can be moved around in
the lexical context without affecting its meaning. Therefore,
discussing transparency on the *syntax* of return, break, continue,
and throw is a meaningless proposition. The only important aspect is
whether the *operations* of returning both from the closure itself and
from the enclosing method, for example, are supported. If you don't
agree with this view on TCP vs. break/continue/return/throw, assume
this pseudo-proposal uses the BGGA_style 'last expression in the
block' for local returns instead; works just as well.

On Nov 7, 12:19 am, B Smith-Mannschott <[email protected]> wrote:
> On Nov 6, 5:54 pm, Ben Schulz <[email protected]> wrote:
>
>
>
>
>
> > > [...] because java is nominally typed. BGGA's (the closure proposal)
> > > biggest downside is that it turns java into a structural/nominal
> > > hybrid, as it introduces stuff like {String, String => Integer} as a
> > > type, which is obviously structural.
>
> > You've asserted that before, prompting a response by none other than
> > Neal Gafter himself [1]:
>
> > "Well, not quite.  List<String> is the same type as List<String> not
> > (only) because they have the same name, but because they have the same
> > type arguments.  That's structural typing, and generics are indeed
> > structurally typed.  As are arrays.  Java is not strictly nominal. "
> On Fri, Nov 6, 2009 at 22:14, Reinier Zwitserloot <[email protected]> wrote:
>
> > It's also a ridiculous line of reasoning. Like most things Neal says
> > when you attack his proposals, it boils down to overly pedantic drivel
> > - technically correct, practically speaking irrelevant or misleading.
>
> > Take this very argument, for example: How else would nominal generics
> > even work? There's no such thing as nominal generics. You could, I
> > guess, create something like:
>
> > public typedef StringList extends List of String;
>
> > But, as you clearly can't create such a typedef for _every_ type in
> > existence out of the box in the java.util package (do we also create a
> > StringListListListListMapSetListListSetMap?), the rule would have to
> > be that any typedef matching 'List of String' matches any other.
> > Regardless of such things as package or name of the typedef. Which is
> > simply another take on structural typing.
>
> I disagree with this characterization. I think Neal's line of
> reasoning, above is sound and his example of arrays demonstrate this
> even more clearly than generics.
>
> With generics, it's at least possible by make a nominal type out of a
> structural type by the simple expedient of:
>
>     class StringList extends List<String>;
>
> With arrays in Java, we can't even do that. Classes and Interfaces are
> the only kinds of types we are allowed to name in Java. This is not
> nonsensical, it's merely impossible in *Java*. It's perfectly possible
> in a language that's more nominally typed than Java:
>
>    TYPE Point3D = ARRAY 3 OF REAL; (* Oberon *)
>    TYPE String = ARRAY OF CHAR;
>
> Oberon is generally very much nominally typed (as you may know,
> judging by the breadth of knowledge demonstrated in your first post on
> this tread) supports naming this type. But even in this language,
> there is also structural typing. Tellingly, one such case are
> procedure types.
>
> TYPE Handler = PROCEDURE (VAR m: Message);
> VAR h: Handler;
>
> PROCEDURE DoSomething(VAR m: Message);
> BEGIN
> END DoSomething;
>
> The variable h, which has a procedural type via the named type Handle
> is assignment compatible with the procedure DoSomething (which is a
> constant) despite the fact that there is no agreement in their nominal
> types. (Procedures don't have nominal types). (How tedious would it be
> if we had to name a type for every procedure we wanted to define?)
>
> So, in summary:
>
> (1) Java has always used a mixture of nominal and structural typing.
> (2) I consider how procedural types are handled in other languages
> I've seen and imagine these design choices were not made without
> reason. I suspect that Closures, in particular, would tend to drive a
> language designer to structural typing.
>
> We can of course argue about whether adding another case of structural
> typing to Java on top of what's already there is a good idea, but
> there's no sense in pretending that Java doesn't already mix both
> structural and nominal typing.
>
> As to BGGA. I've never liked it. Far too much syntactic and conceptual
> complexity for the power it promised. I would have preferred CICE or
> better yet FCM, though that never gained much traction.
>
> // (a different) Ben
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to