Question: can we use Carmack's post to say anything about statically typed languages versus dynamically typed languages? I'm versed in both and like both, so wanted others' opinions. I love(d) Haskell because it pretty much worked if it compiled (but monads are too restrictive); I work in Python because it's what most clients are using. But I read Carmack's post and think that I should be coding in a statically typed language again... No?
[PyCharm is great, but IDEs just don't do dynamic code like they can static code and it hurts.]
You could perhaps use it to say stuff about Haskell or ML vs. Ruby or Python, but not about Java or C++.
The particular errors Carmack talks about are all holes in the type system - they're areas where the type system of C/C++ is unsound (as in the type-theory definition, not the colloquial definition). Null pointer exceptions don't exist in Haskell, because null pointers don't exist; you have to explicitly use a Maybe type. Printf errors do (at least with Text/Printf), but there's a lot of research on dependent types to solve specifically that error.
Again, though, it's a tradeoff. Haskell lets you find a lot of errors at compile time, but the tradeoff is that you spend much more time figuring out why your program won't compile. For a lot of software, you're better off shipping with bugs than not shipping at all. Particularly for exploratory software, it makes more sense to build something that works for your demo just to see if it's useful than build something for everyone that nobody wants to use. Specs that don't meet customer needs are just as buggy as code that doesn't meet the spec.
You can use undefined, the nearest equivalent to null in Haskell, anywhere you like and it is just as bad as using null! However, typically you don't because as you point out Maybe is a better alternative.
> You can use undefined, the nearest equivalent to null in Haskell
I'm not sure you can say that. `undefined` is a case of `error`, so it will blow up any time it's encountered (it's often used to stub code) not just when you try to use it, it's closer to putting a `throw` than to putting a `null`.
`undefined` does not behave like a null though, it behaves much like `error` (it's basically `assert False`), it lets code typecheck but it will instantly throw an exception when executed.
It's usually used to stub code during development in TDD-type scenarios:
myFunction = undefined
myOtherFunction foo = doSomethingWith value
where value = myFunction foo
will typecheck letting you fail your tests.
You can't have `undefined` "pass through" your code the way `null` does.
Sure you can, it doesn't error until it's evaluated, and haskell is lazy, so the failure can occur some distance from the original undefined, and can occur only some of the time.
I sometimes wish I had types in Python. It makes me feel better knowing for sure what a function is returning, or what types I'm comparing. I love Pyton/Ruby and other dynamic languages, but I miss the C++ type system when using them.
You do. They're not statically checked, but they're there.
> I love Pyton/Ruby and other dynamic languages, but I miss the C++ type system when using them.
Why not use a language less syntactically heavy than C++ but still statically typed then? (and C++'s type system? not really going for the stars, are you?) Because a major part of Python and Ruby is indeed that they're not statically typed. A nominative static type system would yield quite different a language, probably something close to Cython[0]. Alternatively, you could fork Python or Ruby with a structural type system, this could be interesting but still — I think — different languages than their originators, not merely dialects. It also would be nothing even remotely close to "the C++ type system" (not that this would be a bad thing, AFAIC). And you probably wouldn't know "what types you're comparing" either.
It's funny how every single one of those features he's wanted has existed in a usable language since at least the 80's.
Hell, Ada has every single feature he wants plus more. I'm particularly fond of the range feature.
type degrees is range 0..359;
It allows you not just to error on incompatible types, but incompatible values for your types at compile time. There's a lot more there, but I'm 100% positive it'll all be ignored by those who need it the most.
I started to write a C++ class to write strongly-type, range-bounded integers (e.g. Fahrenheit and Celcius classes). I gave up when implementing all the operator overloads and my class was hundreds of LOC. C++ really did not to do what i wanted...
except Ada (and maybe pascal) it's something we never see, we all could use this yet it's not there. Kinda like the numerical tower of lisp systems.. anyway.
That is the real issue here. People aren't exposed to these ideas and we keep reinventing them, poorly. Worse, people don't listen to the older more experienced people until after they've already blown themselves up (often more than once).
I'm not sure how to make someone who isn't interested in learning history, learn history. Is this just a result of that our industry is entirely composed of youth?
I found that odd too. In Haskell you have to use monads only for I/O, and for that IMO they are a fine abstraction. (Monads are a fine abstraction to many other things too that have a lot less to do with side-effects.) You are free to use other more general/specialized abstractions in every other part of your code.
[PyCharm is great, but IDEs just don't do dynamic code like they can static code and it hurts.]