3 ms·
You can't really discount the benefits of type inference if you're using the most basic form. Hindley-Milner style type inference feels 1000000x better and IMO
by nv-vn 7y ago
You can't really discount the benefits of type inference if you're using the most basic form. Hindley-Milner style type inference feels 1000000x better and IMO doesn't hurt readability. What I find in real-life code is that the overall structure is way more important than types--I'm not a type checker when I'm reading code, so there's no reason for me to care about what type a function takes. Further, in languages with implicit type conversions, overloading, inheritance, etc. knowing types doesn't really give you much info.
The hardest code bases I've worked with have been very explicit with type info and that's done nothing for me. The examples here feel very contrived; very little of the code in a 100k LoC project is gonna use types like Maps and ints, especially if it's OOP. Knowing that something is an AbstractIterator does very little to help me if I don't know WTF an AbstractIterator is. And complex inheritance chains absolutely destroy my ability to find the method I'm looking for on these types.
Coming from functional programming, it really doesn't feel so different looking up a function vs. looking up a class.
Regardless, every language has some degree of inference, otherwise every function call would be:
let result : int = (f : int -> int)(x : int + y : int, 2 : int)
If your code looks like this:
f(g(x, y), a(b(c)))
then inference isn't really doing much to hurt you. And what I've found is that for any large-scale project you see a lot of type of code.
- pvg 7y agovery little of the code in a 100k LoC project is gonna use types like Maps and ints Why do you think that? Map is a super common Java type, which is what the example with the most Map in it is written in. Hard to see where 'complex inheritance chains' come into it, as well.
- nv-vn 7y agoWhat I mean is that there's a lot more custom types in real world code, and custom types aren't gonna be something you're already familiar with when reading new code. Complex inheritance chains come into this because it makes it hard to track down the code you're looking for. Like let's say we have Cat : Feline & Pet, Feline : Mammal, Mammal : Animal, Pet : Property, Animal : Alive. Now when I do cat.eat(x) it's impossible to predict where eat is defined. Knowing that it's a Cat didn't make it any easier to understand the implementation of eat.
- pvg 7y agoI know what complex inheritance chains are, I'm still not sure how they have much to do with this article. Your comment to me reads like you're trying to forklift a generic critique of OOP on top of this rather slender, content-wise, post. There's not enough in the post to support it and the generic critique is still, well, generic.
- nv-vn 7y agoOOP is a part of it, but what I'm trying to get across is that knowing the type of a variable doesn't make the code substantially easier to comprehend. In small examples it might, but as code scales up abstractions are much more confusing than lack of type annotations. Specifically, complex types can hide important type information far better than type inference.
- ErotemeObelus 7y ago> If your code looks like this: f(g(x, y), a(b(c))) then inference isn't really doing much to hurt you. Err... do you mean to say type inference isn't doing much to help you?
- mrgriffin 7y agoNot OP but I think hurt is correct. My understanding is that if you're passing return values directly into functions then there's nowhere to annotate the types of those values, but many (most?) people are perfectly okay with that even though you could argue that the types are being inferred (in that they're being left implicit, just as they are when you say: var gxy = g(x, y) var abc = a(b(c)) f(gxy, abc)
- nv-vn 7y agoWhat I mean is that the code var a = f(x) var b = g(y, a) Isn't any different from: g(y, f(x)) A lot of real world code I encounter doesn't bother with temporary values for everything and giving them explicit types, which is essentially the equivalent of just using inference here. Thus in this case inference isn't doing anything negative because the code would look like that regardless.
- yxhuvud 7y agoI really like the distinction Crystal makes here, which is that values on the stack is usually inferred, whereas values on the heap is a lot more explicit (though inference can be applied to some level there too, in initializers). It makes it nice to work with while at the same time encouraging reasonable amounts of thinking about memory layout.