7 ms·
> Improved type inference > We want types, not boilerplate. Sometimes it's best to let the compiler figure out what things are by itself. At first I thought t
by TulliusCicero 4y ago
> Improved type inference
> We want types, not boilerplate. Sometimes it's best to let the compiler figure out what things are by itself.
At first I thought type inference was cool too, but more and more I don't like it. I prefer being able to see a variable's type easily, even when skimming over code. Type inference makes code less readable to me.
- rubyist5eva 4y agoMy IDE can show me inferred types as an overlay in my editor (even in languages with dynamic types like Ruby, jetbrains inference is pretty good when the code is simple), perhaps look for an extension for your preferred editor?
- winter_blue 4y agoIf GitHub could dd support for it, then that would be amazing. As it stands, type inference has a tendency to make code reviews more difficult.
- rubyist5eva 4y agoWhy Github? I'm assuming you mean their code review interface, which is so incredibly lacking I don't even bother with it anymore and I just pull the branch locally and use my IDE.
- pnt12 4y agoIt is lacking, but I haven't found practical ways to review it. I tried the github extension in VS code but the experience was even worse for me. Could you share details about how do you do it? I'm very interested!
- rubyist5eva 4y agoThe IntelliJ editor lets me navigate all changed files, full intellisense and lets me add comments and do approvals directly from my IDE interface.
- TulliusCicero 4y agoThen you need that support in every related place, as the other comment about GitHub points out.
- Barrin92 4y agothat's more an issue of editor integration. F# in Vscode for example overlays what types it has inferred automatically.
- TulliusCicero 4y agoAnd what happens in every other tool that displays source code?
- blt 4y agoyeah, to be fair I only know it through the C++ `auto` keyword, but I dislike its overuse. It's great for weird templated iterator types but I prefer to see the concrete type if it's a reasonable length.
- beached_whale 4y agoWith C++’s implicit conversions, it makes that less of an issue though. Like a function returning long and assigning to an int “just works” and can silently trunctate. With auto, both are long
- vkou 4y agoType inference everywhere can make code less readable, but type inference when it's clearly the code author's intent that the type of the variable should not be of much interest to anyone improves readability. A common example of this is a variable that's initialized in one line, fed into another function in the very next line, and then never used again. [1] If the function call that produces it, and the function call that consumes it is named well, the variable's type is often, but not always superfluous. It's like naming for loop variables. Sometimes, you want a specific, detailed name for them. Other times, you just call it 'i', because what it is... Is not very important. It's a counter, counter goes up until we hit the end of a list, don't think about it too much. [1] The two function calls could have been mashed together, but that would make the code less readable. The full variable type could have also been included, but its not very relevant to the intent of the code - which is simply[2] feeding the output of one function as an input into the other. [2] Obviously, when contextual information (like real-world side effects of creating a particular variable - say, a thread, or a record...) that complicates the "Create -> Use" case is relevant, or if the APIs in question have a lot of function overloading, or poorly-named interfaces, or if non-trivial casting is going to take place, it may still be beneficial to explicitly provide the variable type.
- vlovich123 4y agoType inference w/ overlays is usually enough. The only thing I’m missing with VSCode rust overlays is they sometimes don’t show the lifetime on an inferred type which makes it a little more annoying.
- 63 4y agoOne of the things that's made me the most frustrated learning rust is all the type coercion and inferencing. Sometimes code will just work when I have the wrong mental model because types are coerced but then it ends up biting me later when suddenly everything breaks because it can't coerce anymore and I find out nothing was the type I thought it was. I wish there was a way to turn it off while I'm learning just so I can understand what's really happening.
- jgilias 4y agoNobody forces you to rely on type inference. It’s perfectly valid Rust where you type everything if you so wish. This might actually be a good way to learn the ins and outs of the type system. EDIT: Also, what do you mean by type ‘coercion’? As far as I know the types in Rust are never silently coerced to anything. They just are what they are.
- vlovich123 4y agoThey mean inference. Generics get resolved to different types (and lifetimes) depending on surrounding code.
- yetanotherloser 4y agowow, I never contemplated before whether that kind of language design could be evil, but you make me think it might be. Maybe not in the ordinary course of sensible use, but in some horrible "I didn't think of that". Then I feel a bit hypocritical because I'm sure I've relied on a hundred more problematic abstractions without worrying about it.
- kibwen 4y agoFar from evil, it's amazingly useful, and is why things like `let x: Vec<_> = foo.collect();` work (the return type of the `collect` method is generic). Rust stops type inference at function boundaries, so the precise type of something is never far away if you need it.
- treis 4y agoThe problem is when you get things like: var someLongThing <application.someHierarchy.someLongAssPackage.someLongThing> = new application.someHierarchy.someLongAssPackage.someLongThing()
- hinkley 4y agoclass class1<T extends Comparable<T> > implements SmallestLargest<T> T[] values; This is a spot where inference doesn't work, but has the same problem as the relatively tame example you used. The solution here is not to eliminate the type signatures. The solution is not to wait until compile time to figure out the type of a thing. Nominal typing, as in named types, is the solution here. If you have a 'thing', which also happens to be an application.someHierarchy.someLongAssPackage.someLongThing implements application.someHierarchy.someLongAssPackage.someInterface, anotherLongAssDefinitionForTheReturnTypes but that's an implementation detail, not a type description. It's an Address, or a customer impression, or a similar product, or a fuel tank. Just fucking call it what it is instead of pretending like you're working on your PhD thesis. Your coworkers aren't robots, or academics, they're human beings who've got real work to do and kissing your architectural astronaut butt/complementing your farts are not on the list. Name things like a human. A wise human, but a human.
- orlp 4y agoNot really, that is solved with aliases. The problem really comes to life when using strongly typed generic functions that must be generic over their return type. This most notably occurs with Rust iterators. Try writing out the type of this thing explicitly: let pos_nums = v.iter().map(|s| s.parse::<u64>().unwrap()).filter(|n| n > 0); Hint: you literally can't in current Rust because closures have Voldemort types, you can't name their type. And even if you could, the resulting type would be horrendous.
- spullara 4y agoI try to avoid using it where the type isn't obvious from the context. But when it is, I like it a lot.
- matsemann 4y agoType inference locally is great. Doing `val something = MyClass()` or `val something = someFunc()` . No ambiguity, just less typing and clutter. At bounds however (function input/output for instance) I prefer explicit types, less chance for mistakes and the signature acts as documentation to what the function does.
- 1337shadow 4y agoStatic typing removes freedom I am addicted to with duck typing, however, I only ship TDD code which also serve as coding documentation. Both are protective but if you're not writing tests then by all means use static typing.
- yetanotherloser 4y agoI'm finding this hard to relate to. Our circumstances and experiences must be pretty different. But I'm afraid to me that sentence reads a bit like "I have a lathe so I don't need a bicycle". You or I might not do bicycle jobs, or lathe jobs, but it's a bit of a stretch to imply one renders the other irrelevant. I find it interesting that you characterise static typing as about safety. I think it's more about communication. (for me this includes "communication to myself when I wrote this seven years ago and didn't think about it since", which I appreciate may be a bit of an edge case). Tests are also a great medium of communication, but a different one - in which case the metaphor becomes swap a sonnet for a sonata? I'd like both please, but maybe not always at the same time :-D
- dmitriid 4y agoNeither tests nor types are documentation.
- RHSeeger 4y ago> if you're not writing tests then by all means use static typing I know you're not saying this, but your wording implies it to a bit... Tests to cover <the things covered by static typing> are only one of the uses for automated testing. There's plenty of places (most of them) where automated testing is just as useful with a statically typed language.
- jandrese 4y agoOr the question you should always ask: What if the compiler gets it wrong? Is there a way for you to tell?
- MaxBarraclough 4y agoCompiler/runtime bugs are always painful, I don't see that type inference is a special case there. Fortunately such bugs are pretty uncommon.
- jandrese 4y agoIs it a bug if the compiler thinks that maybe the value could grow too large to fit in an integer so it promotes it to a floating point type. But then you compare it to a value that is converted out of a string of ASCII digits and the comparison is off by 1 because 4 != 3.99999999996 and this causes your code to iterate one additional loop which doesn't cause an immediate problem except about 1 in every 256 times it causes a boundary condition where the next packet will have a corrupt first byte? Technically the compiler technically did nothing wrong, but you are still left with a head scratcher because all of the logic seems sound and yet it produces occasional garbage.
- adgjlsfhk1 4y agotype inference isn't magic. It would absolutely be a bug for the compiler to change the type of a variable from an int to a float because it thinks there will be overflow.
- ben-schaaf 4y ago> Technically the compiler technically did nothing wrong I don't know a single language where integers are "promoted" to floats when they get large; certainly no statically typed language. You could argue JavaScript does this, but it's neither compiled nor does it actually have integers. So yes, if a compiler did that it would be a bug.
- duped 4y agoWhat compiler does that? What you're describing sounds like a weirdly designed type system, not a compiler that implements it. That said, this is an example of the compiler being wrong. If a value is changed to a data representation with different comparison semantics, and later compared to a different value of a different representation, it means the original optimization (hand wave over the definition of that) was unsound in the first place. AOT compilers would classify this as a bug that needs to be fixed imminently, and JIT compilers that do this kind of thing use something called dynamic deoptimization to remove the change once its been invalidated.
- dkarl 4y agoExplicit types are useful in some places. Type inference doesn't mean you can't use them, just that you don't have to spell them out everywhere even when they aren't useful.
- nextaccountic 4y ago> I prefer being able to see a variable's type easily, even when skimming over code. Type inference makes code less readable to me. An IDE can still show the inferred types!