Hacker News new | past | comments | ask | show | jobs | submit login

It is certainly subjective, but i am one of those developers who dislike inference in languages where it has them and prefer explicit typing out types - in fact i also go as far as to avoid type aliases (e.g. i prefer something like "const std::vector<some_template<some_foo>>" to "a_foo_vector" typedef for the former).

The reason is that i want to know "on site" what exactly is going on when reading and debugging code, especially outside a "smart" IDE, like when diffing changes via the command line, a web-based VCS frontend or some code review tool - especially since these tend to not show the entire code, meaning i need to switch back and forth. But even with an IDE that can show me the inferred types, it is almost always (while i say "almost always" i really mean "always" since i haven't seen any other, but there might be some IDE i haven't tried) done through some popup under the mouse cursor, meaning it is transient and slow.

For similar reasons i dislike features like operator overloading, placing non-self-initializing logic in constructors (and the equivalent in destructors), properties for anything that involves complex calculations (unless the language uses special syntax for properties that make them stand out when used) especially for getters, i prefer to use names that hint to what the code does (e.g. i'd use something like "get_foo" only if it doesn't do any calculations and give you a precomputed or cached "foo", otherwise i'd use an "action" verb like "calc_foo" or "find_foo" or whatever to hint that there is some calculation going on and isn't just a dumb getter), i avoid exceptions as they create hidden exit points for functions (and if the IDE/editor allows, i use a more visible - like bold red - font for "return" or the language equivalent so that explicit exit points are obvious), etc.

Yeah, these make code more verbose and you need to type more, but IMO the negatives are grossly overwhined against and while the positives way too overlooked.




> who dislike inference in languages where it has them and prefer explicit typing out types

So you prefer

    std::vector<some_template<some_foo>> foo = new std::vector<some_template<some_foo>>();
Rather than replace the first one with var / let / auto / whatever your language does? Why? The type is already there.


In terms of "liking" it, no, in that very specific case where the type is repeated and very long, i do not like it and i think "auto" (or var or let or whatever) looks better. However in the interest of consistency (and to a lesser extent, avoiding 'slippery slopes') i'd rather type that than use auto.

And even then that this is only in the very specific case you showed, where the type is too long, it is repeated and the constructor parameters - if any - are visually dwarfed by the duplicated type.

In practice these aren't as common as other uses of types like loop iterators for member/obtained collections (where the use of 'auto' makes it impossible to know the collection type unless you check the collection declaration) or local variables you assign to the result of some function (the return type of which again you need to check the function declaration to see) and - at least in C++ - you rarely need to do "very_long_foo* bar = new very_long_foo" as a stack allocated "very_long_foo bar" is enough (so no need to double type the type).


Maybe you're getting mixed up with Java, but that example type is wrong, since you used `new`, the vector was allocated in the heap and the appropriate type is a pointer type: `vector<T>*`.

What's more, that's a highly unusual example. Rarely would you need to heap allocate a vector. In the case of stack allocation the syntax would be `vector<T> myVec` which is as succinct as possible.


Personally I think that just makes code harder to read, and more difficult to refactor. You get benefits from leaving things inferred in some places when refactoring, preventing you from having to change a bunch of additional signatures just because you made a single change.

And the language you use is probably using aliases too in it's stdlib, so why hate on aliases? They are a great way to abstract away the details.

The boundary I prefer is to explicitly type function signatures, and leave everything else (or as much of it as I can) inferred.


TBH i only have statically typed languages in mind (like C++ and Free Pascal), so i'm not sure how it'd work in a dynamically typed language with type annotations, but to refactor i'd just... change the type and then work through the compiler errors to find the places that need their type updated. Some IDEs also provide you with tools to find all those uses and even can do the refactor themselves.

Your refactor will contain more lines of code since it'll need to also contain the updated use sites, but i do not see that as a problem at all - and even if it is one, it is only a short term small problem that is certainly not as important as having the code more obvious and readable in the long term (assuming of course you feel the same about readability as i do - after all as i wrote in my message above it is a subjective issue :-P).


> dynamically typed language with type annotations

I'm talking about statically typed languages also, just ones with inference. Haskell, Rust, Ocaml, F#, Go, etc, and increasingly languages like C# and Java are adding more and more inference.

Your response makes me think you don't really get what type inference is.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: