4 ms·
>both static and dynamic languages have existed for over six decades For a long time however, if you wanted a mainstream (well supported, large ecosystem) lang
by realharo 8y ago
>both static and dynamic languages have existed for over six decades
For a long time however, if you wanted a mainstream (well supported, large ecosystem) language with static typing, you pretty much had to deal with languages like Java or C++, with their pretty limited type systems and other unrelated design choices that may not appeal to you. It was either that, or going full dynamic. Or some niche language with poor library support.
These days there are plenty of popular languages where you can get all the benefits of static typing with far fewer compromises (Kotlin, Swift, Rust, Scala, TypeScript, etc.) AND a more expressive type system. So the field has definitely changed.
- deleted 8y ago[deleted]
- tabtab 8y agoKotlin, Swift, Rust, Scala, and TypeScript still have small user bases. Java, C#, and C++ are the most prominent static-typed/compiled languages. I see no evidence the first 5 listed are eating into say Python, PHP, and JavaScript.
- norswap 8y agoThe type system of Kotlin is pretty much the same as that of Java (the only addition is that of declaration-site variance, which essentially allows you to elide some of these annoying wildcards at the use-site). I'm not familiar enough with the others, but I have A LOT of doubts. Only Scala's type system is clearly more powerful/expressive than Java. Also, through templating, C++ type system is made quite expressive.
- realharo 8y agoCompared to Java, Kotlin also adds nullable types and sealed classes. The built-in syntax for lambda types could also be considered a part of the type system. Or the fact that inline lambdas let you use non-local returns (https://kotlinlang.org/docs/reference/inline-functions.html#non-local-returns https://kotlinlang.org/docs/reference/inline-functions.html#...) where the explicit `inline` can be considered a part of the type. As for the others, check out for example TypeScript's mapped types (https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types https://www.typescriptlang.org/docs/handbook/advanced-types....), or Swift's extensions (https://docs.swift.org/swift-book/LanguageGuide/Extensions.html https://docs.swift.org/swift-book/LanguageGuide/Extensions.h...). Considering that Java or C++ don't even have sum types, it's not exactly a high bar to cross.
- norswap 8y agoFair point for nullables, although that is already possible through annotation processing (see the checkers framework) - but there is a good faith argument that this isn't "core" enough. The syntax for functions and inlining are not part of the type system. Inlining especially, is a useful language feature, and has to be checked at compile-type, but is unrelated with types. Sum types, really you can have that with just inheritance (base class with package private constructor + final sub-classes). What Java lacks is a nice way to pattern-match/switch over types (which Kotlin does nicely with flow typing), but again that isn't really the type system (although it does make the type system nicer to use, certainly).
- realharo 8y ago>Fair point for nullables, although that is already possible through annotation processing (see the checkers framework) - but there is a good faith argument that this isn't "core" enough. It also wasn't available in a practically usable form until relatively recently (when talking about history), so my very first point about the timeline of languages still stands. Plus it adds even more verbosity to an already very verbose language. >The syntax for functions I meant function types, e.g. the variable `val a = {}` has a type `() -> Unit`, which is a real type in Kotlin. Of course you can achieve a similar thing in Java with SAM interfaces (including all the weirdly named ones in `java.util.function`), so I'd call that the same level of expressiveness. I don't see why `inline` wouldn't be a part of the type system, when you can have a function argument (that is itself a function) that either - can be passed into anything that expects a function as an argument - as long as the rest of the type matches of course (a non-inline argument) - can only be invoked or passed into another inline function (an inline argument) Conceptually, this has some parallels to C++'s const-correctness ("any matching pointer can go here" vs. "only a non-const pointer can go here", "this function cannot be called via this pointer" etc.), which is generally considered a part of its type system. It's just a matter of definition really. >Sum types, really you can have that with just inheritance (base class with package private constructor + final sub-classes). The person that uses those classes (I'll call them consumer), e.g. writes a function that takes the base class as an argument, then has to be aware of the internal implementation - the compiler won't help you there. If someone else who maintains that part of code adds a new subclass, you'll have an unaccounted for possibility and there is no way to safeguard against that (unless you redesign the whole part of the codebase using crutches like the visitor pattern). There is no good way to express "this value can be one of these types, but no other" in Java's type system from the consumer's point of view (only from the producer's). I may not be using the correct terms here but hopefully you get what I mean. As far as the Java compiler knows, you are not really expressing a sum type, and that comes with the mentioned negative consequences.