Hacker News new | ask | show | jobs
by JoshTriplett 4672 days ago
> A hypothesis I have on Ruby is that people attribute dynamic typing to it being a productive language, but that Ruby is actually productive for other reasons, in spite of being dynamically typed.

That has always been my reaction to most comments about dynamically typed scripting languages, including Python and Ruby. Most of the time, turning compile-time type errors into runtime exceptions is not a feature.

2 comments

Yes, but the upside is you avoid the complexity headaches of interfaces and covariance/contravariance and generics and all that stuff.

Heck, look at all that FactoryFactoryFactory stuff you have to deal with when you want to swap out core parts of a framework - you end up with config files and XML and you have to make sure the guy who made the original framework designed it to allow you to change the part you want to change with your modular swap... in a dynamic language? Monkey patch. It's ugly, but it works.

Heck, look at serialization. If you want to serialize/deserialize static objects, you need metadata that includes the types of everything - stuff like XSD in XML. Dynamic languages don't need that stuff, which is part of the modern popularity of JSON... Javascript and its buddies just play nicer with JSON. I actually wish there was a popular simplified analogue to XSD for Json because I actually miss the ease of serializing into objects that you get using XML/XSD in C# or JSON in Javascript.

The dynamic-ish nature of exceptions that seem like an unholy abominatable hole in the type-system in static languages (or a source of unending-agony in Java's checked exceptions) suddenly fit nicely into a dynamic-typed language paradigm. Python embraces a "easier to ask forgiveness than permission" approach, throwing exceptions willy nilly and it makes nice clean code.

Plus, working in a dynamically typed language heavily discourages premature optimization because you already threw performance out the window.

But yeah, you're basically working without a net, and that kinda sucks.

What you describe is not a problem of statically typed languages in general, but of Java in particular.

Try Haskell for static typing done right.

Or any other language in the ML family.
> Yes, but the upside is you avoid the complexity headaches of interfaces and covariance/contravariance and generics and all that stuff.

Maybe it's a matter of what you are accustomed to but not having explicit declared types gives me headaches. I find code without types horribly unreadable - because I can't see at the first glance what data a function processes, etc.

Also dynamic typing and its runtime type checking gives me that uncanny feeling of "something might be wrong but I won't find out till I hit it".

It's absolutely a feature. It allows testing small parts of a system during a major code change when the rest of the system is broken.
You can easily do that in a statically typed language as well; you just have to do it explicitly. For instance, Haskell has the error function, of type "String -> a"; you can use it absolutely anywhere, no matter the expected type, give it an error message, and if the value it produces is ever actually used, it throws an exception with the specified message.
Also the trace module is pretty useful for the kind of dynamic-debugging practice people often do.
Don't discount the value of doing it implicitly. When you're just throwing stuff together (and there is a place for that), it's a distraction to work around parts of the system that won't work yet, both the typing and the mental overhead.
Then provide compile-time warnings---something still not done. Haskell's GHC now does -fdefer-type-errors
As well as applying patches to a running system without restarting it
Having done this both with Clojure and Erlang, I find the unversioned, dynamic mode of achieving this is fraught with trouble. It's really easy to end up in complex atypical states during upgrade which can at best be hard to debug and worst corrupt other, longer term state.
Exactly. I think what a lot of people miss is that erlang makes live upgrades possible but certainly not easy. Trying to upgrade a complex application one component at a time (the way erlang/otp promotes) is still insanely hard and not worth the pain unless you're working in a domain where you have absolutely no choice (which is of course why Ericsson developed erlang in the first place). For the vast majority of applications the right choice is to restart the server and accept a few seconds downtime.
I think with better documentation I'd actually call Erlang's model "easy" in that its really easy to do things correctly with absolutely minimum chance of corruption/failure/non-repeatability. OTP gives you the tooling—releases, versions thereof, and simultaneous multiple module tenancy being key—to actually do a good job. That's a rare thing.
There is essentially no reason why this should ever be needed.
Unless you're an Erlang or maybe Smalltalk programmer