4 ms·
> Having said that, Java is a typed, safe OO language, and that alone, I contend, already makes it close in spirit to ML (in particular, its structures/signatur
by catnaroek 9y ago
> Having said that, Java is a typed, safe OO language, and that alone, I contend, already makes it close in spirit to ML (in particular, its structures/signatures).
The whole point to structures and signatures is abstract types. Mere value hiding can be achieved with let, which isn't exactly the pinnacle of typing: Scheme has it.
> I think interfaces (and the ability to override methods like `equals` are pretty close to abstract types.
Please do tell how you would make two or more instances of an abstract type in Java, in such a way that:
(0) The client is aware that that the two instances have a common type.
(1) The client is not aware of the representation.
If it's not possible, then Java doesn't have abstract types, period.
> That it can be circumvented is what makes code and data sharing between different languages with different variance models possible
And unsafe. (No, memory safety alone isn't safety.) If it's going to be unsafe, then I better at least get my money's worth in terms of performance, which is why low-level languages like C and Rust are the only ones worth FFI'ing to.
> I can understand those that think that Java not being fully static or fully dynamic may defeat the whole purpose of what they like in their preferred approach.
Java is fully dynamic. “Type checking” in Java is basically a mandatory linter.
- pron 9y ago> Please do tell how you would make two or more instances of an abstract type in Java, in such a way that... By having two implementations of a common interface, like `ArrayList` and `LinkedList` both implementing `List`. > And unsafe. It seems like you're defining "safe" to be precisely what the languages you like provide, no more and no less. I can say that ML and Haskell are unsafe because they don't statically forbid erroneous behavior at runtime, like a sorting function that doesn't sort (or doesn't terminate). Java has no undefined behavior. In fact, it is completely unknown how much safer -- if at all -- is ML than Java in practice. > If it's going to be unsafe, then I better at least get my money's worth in terms of performance, which is why low-level languages like C and Rust are the only ones worth FFI'ing to. Of course it's a matter of specific requirements, but I think you get more than your money's worth in terms of performance in Java, and having decades of experience writing huge multi-MLOC programs in both Java and C++, I'm convinced that it takes significantly less effort to get a well-performing large Java app -- especially if it's concurrent -- than a C++ app, even though you could surpass Java's performance given considerable additional effort. In any event, I think that the success of the JVM shows that many people find supporting it to be worth it. > Java is fully dynamic. “Type checking” in Java is basically a mandatory linter. This is simply untrue. Java is mostly type safe. If you have a variable of type `Foo` in your program, it cannot reference an object of a type that is not `Foo` at runtime. You are right that this does not extend to generic types, but only if -- 1. you've intentionally tried to circumvent the type, or 2. you've fallen victim to an obscure bug that was found recently, and is very hard to reproduce accidentally.
- ratmice 9y ago>> Please do tell how you would make two or more instances of an abstract type in Java, in such a way that... >By having two implementations of a common interface, like `ArrayList` and `LinkedList` both implementing `List`. This is not i believe what he is talking about, here is a silly example in SML, it has 3 types which all share a type t... a list of t pairs, a vector of t's, and a function from pair of t's to t. functor Foo (type t; val pairs : (t * t) list val f : t * t -> t) = struct val things : t vector = Vector.fromList (List.map f pairs); end One thing to note is that t is never exported/returned. and thus, the thing returned exports t vector but not t. we could export t in a few different ways: type t = t; Export it, let its binding be known type t; Its a type, but what it is bound to is not known.
- catnaroek 9y ago> By having two implementations of a common interface, like `ArrayList` and `LinkedList` both implementing `List`. That's not an abstract type, it's an object type. An abstract type has a single representation, determined by the type's implementor, which is hidden from the rest of the program. OTOH, objects with the same type may have different internal representations, determined by whoever constructs the object, just as in your example. > It seems like you're defining "safe" to be precisely what the languages you like provide, no more and no less. Safety is defined in terms of the language's semantics, not my personal preferences: are meaningless operations ruled out or not? (We can get technical and say that Java does, in fact, assing a meaning to invalid casts: to throw ClassCastException. But very few people would consider that a useful meaning: if you run into it, your program plainly has a bug.) > Java is mostly type safe. Then it isn't.
- pron 9y ago> An abstract type has a single representation, determined by the type's implementor, which is hidden from the rest of the program. So, like: <T> foo(A<T> a, B<T> b) { ... } You don't know what `T` is, but you know that `a` and `b` are parameterized by the same type. > Then it isn't. That it's not completely typesafe (Scala isn't, either, BTW) doesn't mean that it's not completely safe. The vague notion of safety is not defined by the arbitrary notion of type safety, which heavily depends on the type system. TCL is typesafe, but few would say it's safer than Java. > But very few people would consider that a useful meaning: if you run into it, your program plainly has a bug. There are many more plainly incorrect behaviors that aren't prevented even when the language is 100% type safe (depending on the type system, and the effort required to encode the correctness conditions) -- as Java prior to generics was, BTW. So if you want to define "safe" as "typesafe", that's fine, but given than ML's and Java's type systems are of similar (not identical, but similar) richness (i.e., they are both simple type systems with parametric polymorphism), and given that you don't actually run into `ClassCastExceptions` in Java unless you choose to do stuff that can get you into that sort of trouble (which would mean ignoring compiler warnings), I think the two languages offer a similar level of safety.