Hacker News new | ask | show | jobs
by garethrowlands 1652 days ago
Premature or wrong anything is clearly bad. But is parameterisation a premature or wrong abstraction? I'd say that parameterisation - even in the type language - is the original proven abstraction.
2 comments

I think this is why I always have trouble understanding arguments against generics (in the general case at least). Parameters are added to functions/methods in order to make them more generic/flexible, as a rule. To move something that may have been hardcoded into something that can now be configured:

  get_data() { filename=default ... }
  =becomes=>
  get_data(filename=default) { ... }
When the type either does not matter, but the concrete instance records it, or the type makes sense to be configurable, you want generics. As a silly example (but short enough to fit into a comment block):

  fn nth(seq: [int], n: int) -> int
Now you have to make a new nth for every single sequence type, even though it has no bearings on the actual operation. Or you make it generic:

  fn nth<T>(seq: [T], n: int) -> T
That's a trivia case, yes. But if anyone has ever worked on a complex code base there are plenty of situations like this that turn up, at least in my experience. Sure, I almost always start off with concrete instances with a fixed type, but as soon as it becomes apparent that the type itself is irrelevant and I have a couple use-cases with different types, why not make it generic and be done with it? Like, would you really have more than one version of that get_data function running around, one for every conceivable filename? That would be obscene. Why would you do the same with types?
Yes, in my opinion oftentimes it is.

There is a reason why even in mathematics people like to operate on concrete examples to get an intuition. For many, concrete is much easier to understand than abstract.

That's the less important point. The more important point is that making your code generic often involves more trickery which makes the code more complex, even if you only use the code once or twice - so that's just effort wasted.

The fact that parameterization is a proven abstraction doesn't mean it's good everywhere. Same as I don't agree with the "Clean Code" way of creating a myriad of 4 line functions.

Yes, good programmers won't make these mistakes, you can totally handle them. But when arriving at legacy code or open-source projects I greatly prefer to find under-abstraction rather than over-abstraction.

To be clear, I'm not against generics, I just agree with the parent of my original message. I'm worried people will overuse them and I don't want a whole laundry list of Rust features in Go. I'm very happy about libraries with type-safe generic B-Trees.

I get what you mean, and I personally rarely write generics, but when I need them they're great. I think that a good rule of thumb that would be easy to implement and review would be "no generics outside of libraries". This way, you get your type-safe containers, your application code doesn't get much more complex than before, and if you want to introduce generics, you have to really think about it.