3 ms·
> templating Yes, running arbitrary code at compile-time can produce arbitrarily complicated results if you're not very very careful. This is not a type system
by nyssos 3y ago
> templating
Yes, running arbitrary code at compile-time can produce arbitrarily complicated results if you're not very very careful. This is not a type system issue: lisp macros are just as dangerous.
> abstract base classes
Again, nothing to do with types: your complaint is with Java-style OO. Which is garbage, but for historical Java-specific reasons. Using Java as your prototypical example of a typed language is like using PHP as your prototypical example of a dynamic language. There's no such thing as a feature good enough to rescue a bad language. That doesn't mean no feature of a bad language can ever be good.
> generics
Generics produce strictly simpler code than copy-pasting the same implementation over and over again. That's their entire purpose. A generic function isn't a way to give the same name to different pieces of code (the way that inheritance is, for instance), it's literally one function: `mapIntList` is `mapFloatList` is `mapStringList` is `mapIntListList`, all the way down to the compiler output. Unless you're doing some pretty serious performance optimization, giving them different implementations is a bug. And you wouldn't do so in a dynamic language either!
> non-trivial user defined types
These exist as part of your program structure whether you like them or not, the only question is whether they've been made explicit.
> Consider a simple program that adds 2 numbers: a & b together. In a dynamically typed language, this would be a + b. In a statically typed language, once you consider overflow and underflow, you will likely have a hundred lines of code.
Considering overflow and underflow in the static case but not the dynamic case is stacking the deck. Either you're using arbitrary-precision numbers or you're not.
Here's Haskell code for adding two numbers:
add :: Num x => x -> x -> x
add a b = a + b
If you don't want to worry about overflows, you use `Integer`s, which are arbitrary precision. If you're worried about performance, you use `Int`s, which are machine integers.
You can complain that this isn't "really" the addition code, since we're calling out to the `Num` instance, but the same applies to dynamic languages. Python's `a + b` is calling out to `__add__` in exactly the same way.
> This creeps up again in JSON parsing where the types really are defined at runtime.
They are not. The type of arbitrary JSON is (using Haskell again)
data JSON =
| JSONNull
| JSONBool Bool
| JSONNumber Double
| JSONString Text
| JSONArray [JSON]
| JSONObject (HashMap Text JSON)
(You don't have to use a hash map, of course: decoding the raw text stream to JSON is a separate step). You then check that it has the structure you expect by implementing a function `jsonToFoo :: JSON -> Either MyPreferredErrorType Foo`.