3 ms·
> 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
by 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.
- catnaroek 9y ago> So, like (...) You don't know what `T` is, but you know that `a` and `b` are parameterized by the same type. Abstract types are existentially quantified, whereas generic type parameters are universally so. > Scala isn't, either, BTW Scala isn't type safe either, period. > 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) Actually, Java's type system is more complicated, since it has subtyping, as well as a limited form of first-class existentials (wildcards) that Standard ML doesn't have, yet somehow Java buys me less safety than Standard ML. This is what happens when engineers design programming languages. > 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. There are no runtime type errors at all in Standard ML.
- pron 9y ago> Abstract types are existentially quantified Oh, you mean something like this? interface A<T> { T x(); void y(T t); } void foo(List<A<?>> as) { // every element may have a different instance of T for (A<?> a : as) bar(a); } <T> void bar(A<T> a) { T t = a.x(); a.y(t); } > There are no runtime type errors at all in Standard ML. There are no runtime type errors at all in TCL, either. That doesn't mean that the language is safer. "Safety" and "type safety" are not the same. Type safety has its virtues, but I would argue that Java's type safety is good enough; I would take it along with its dynamic capabilities over SML for many projects -- it's just a tradeoff that buys you a lot of other stuff. There's a price you pay for dynamic runtime capabilities and for deep cross-language interop (e.g. a Clojure list is a Java List), and that's a price worth paying in many cases, considering that it's not high at all. > This is what happens when engineers design programming languages. I guess engineers prioritize things based on what they're actually worth to developers (or, at least, according to how much they believe they're worth to their developers) as opposed to using an arbitrary metric for some intrinsic quality, whose relationship with actual benefit isn't at all clear. Java sacrifices a tiny bit of type safety for interop and various dynamic capabilities. I wasn't aware that there's been some major discovery showing that this is the wrong tradeoff to make.