Hacker News new | ask | show | jobs
by foxfluff 1616 days ago
Static languages unfortunately don't save you from that. You find automatically inferred types, or types that refer to some abstract interface or template-class-mess but you have no idea where the actual implementation lives until you compile with RTTI and run it under a debugger... and as tfa posits, people working with the limitations of static languages often end up reinventing a dynamic structure.

Is this somehow supposed to relevant to the posted article or did you just want to start a tangentially related dynamic-vs-static flame war here in the comments section?

4 comments

> Static languages unfortunately don't save you from that.

While you still can make a static language that is confusing, it's a lot harder... I challenge you to write a function signature in Rust that is both:

1) Useful

2) As opaque as the python signature above.

> You find automatically inferred types

A minority of static languages do type inference in function signatures. I think it's a bad idea for exactly the same reason the python code is bad. On the other hand, every dynamic language allows you to omit any information about a type signature.

They usually save you from that particular pitfall, but not always of course.

Static vs dynamic makes for such difference in the detailed workflow, both in terms of changing existing code & in terms of writing new/(more) from scratch code, yet they can both be quite fruitful, and can both be abused in absurdum.

It seems like people naturally fall into one of the two camps (either by personality or by training), and the other side just seems kind of insane: "how can you even work that way!?". Then culture and idioms emerge over time and strengthen the tribalism.

I've gone back and forth between the two over the course of my career, and it's quite a mind-shift when switching, with a fair bit of pain involved ("but it would be so easy to do this in [old language]", or "what the hell is this garbage anyway!?") and then eventually it settles in and it's not all painful, all the time ;)

(Going back and forth between Scala and Python right now, so this hit a bit of a nerve)

> Static languages unfortunately don't save you from that. You find automatically inferred types,

Oh yes, they do. Even inferred, the types are there and pretty easy to locate, even if you're not using an IDE.

The types are there.. but you don't know which one it is that your program is dealing with. You could have dozens of implementations for any given abstract interface. One gets picked up at run time.
You don't need to know which one, because the abstract interface tells you how to use it...
That's the theory. Works great when there are no bugs and everything's been designed just right. In that world you could wipe implementations from memory because you won't ever need to dive in..

Very often I'm looking at code and "how to use the interface" is not a question I'm looking to find answers for.

Some information is a lot better than none. In some cases you might want to know what implements the interface: that information is also statically available. In Rust, you can look at a trait and see what types implement that trait.

If you need to know exactly which implementation is being used in a particular context then maybe you shouldn't be using an interface, but should be using the concrete type?

> If you need to know exactly which implementation is being used in a particular context then maybe you shouldn't be using an interface, but should be using the concrete type?

Look again at the original comment by dandotway. It's not a question of "what type should I be using here", nor is it "how should I use this interface", but "what do I need to do to understand this code?". Even if an abstract interface is used correctly and is the right thing to do, you still need to understand the code before you can (debug|rewrite|extend|whatever) it.

And it's a pipe dream to say you can look just at the interface. Something blows up, is it the interface used wrong? Maybe, maybe not? Is it the interface implemented wrong? Maybe, first you need to know what implementation you're looking at. Subtle interactions between abstract and concrete send you spelunking through the layers when you're debugging or trying to extend the interface to account for something the original author didn't anticipate, and often the devil (in the details) comes from concrete implementations.

> to some abstract interface or template-class-mess

And traits! "Oh look, this functionality is implemented in a trait implemented by a trait implemented by a trait implemented by what you're looking at. Maybe"