5 ms·
You assume that the point of using types is readability, which is false. Types let the compiler reject a large set of invalid programs, which would otherwise p
by tzahola 8y ago
You assume that the point of using types is readability, which is false.
Types let the compiler reject a large set of invalid programs, which would otherwise produce a runtime error in a dynamic language.
for (auto foo : foos) {
foo.bar()
}
I don't care about the exact type of `foo`, so I let the compiler deduce it behind the scenes. However, I still want it to break my build if `bar()` doesn't exist!
- mlthoughts2018 8y agoYour example does not convince me. As a code reader, I would care very much why does foo have a bar() method. Is it because foo is a Widget or a subclass thereof? Then I can backtrack to understand the implementation being inherited. Or maybe it’s some other class that uses bar() for a totally different purpose. Who cares if the compiler can deduce it. That’s not helpful to me at all if I am scanning this section of code because I have to add more method calls inside the loop to calculate new results, and I don’t know what base type foo even is to get started with what would be required. > “You assume that the point of using types is readability, which is false.” This just seems wrong to me. Communicating your designed intention with type annotations is the number one reason to use them, whether you’re writing C++ or Haskell. Getting the compiler’s help to prove correctness or avoid bugs is a secondary reason. Sometimes it becomes the primary reason in isolated cases. But usually it’s a secondary consideration nowhere near as important as using types to communicate the design of the program.
- jcelerier 8y ago> This just seems wrong to me. Communicating your designed intention with type annotations is the number one reason to use them, whether you’re writing C++ or Haskell. sure, but most haskell programs leave type annotations out, it's only some specific parts where it enhances clarity that it helps ; most of the time it would be unneeded noise, just like in C++. I really don't want to go back to the dark days of for(std::vector<std::pair<float, int>>::const_iterator it = v.cbegin(), end = v.cend(); it != end; ) { if(it->second > 1 && std::distance(v.begin(), it) % rand() == 0) it = v.erase(it); else ++it; } versus for(auto it = v.cbegin(), end = v.cend(); it != end; ) { if(it->second > 1 && std::distance(v.begin(), it) % rand() == 0) it = v.erase(it); else ++it; } In a lot of cases, it can even cause bugs : for instance, the iterator type of std::map<int, std::string> is std::pair<const int, std::string>. If you ever happened to write : std::map<int, std::string> map; // ... const std::pair<int, std::string>& value = *map.begin(); then congrats, you have unneeded memory allocations because the pair will be copied in order to match the explicit type. whereas here : const auto& value = *map.begin(); you know that you get exactly the correct type - maybe at some point you will replace with a boost::flat_map or another which has a different iterator type, and when you do this, you won't need to change any other code anywhere else - it will be automatically correct.
- mlthoughts2018 8y ago> “sure, but most haskell programs leave type annotations out, it's only some specific parts where it enhances clarity ” This is very false, I can tell you from having written Haskell in production for several years. It’s widely regarded as an anti-pattern in Haskell to leave out type annotations, even for constant values, except in the most trivial of cases. Type annotations are a design feature of Haskell. You usually use the “type” keyword to define custom type names for primitive types just to give them descriptive, application-specific names, like type PhoneBook = [(Name, Number)] just so you can add more explicit annotations and communicate the flow of your program very explicitly in the type annotations. You definitely do not look at it like minimally using type annotations “only where it adds clarity” because the whole point is that as the code author you don’t know where clarity is needed. That is for the code reader who has to change your work later on. Incidentally, I actually very much think that your first example of that for loop at the bottom is a lot clearer than the one using auto. Just make a descriptive typedef / typename of that long const_iterator type. Make something readable so that we know why there is a vector of pairs of (float, int). If you want to cut down the syntax there, auto is not the right way. A descriptive typedef is the right way using type alias names that communicate your intended design.
- jcelerier 8y ago> You definitely do not look at it like minimally using type annotations “only where it adds clarity” because the whole point is that as the code author you don’t know where clarity is needed. That is for the code reader who has to change your work later on. Are you serious ? In standard Haskell you can't even add type annotations to bindings, that's how much type annotations are relevant to the language. They're only available in type & function definitions. I seriously doubt that you use {-# LANGUAGE ScopedTypeVariables #-} and that all of your code looks like main = let (x :: Integer) = 123 in print $ x That's literally what you expect C++ programmers to do when you ask them not to use auto, and I've absolutely never seen production Haskell looking like this - common Haskell is much closer to this : https://github.com/ivanperez-keera/haskanoid/blob/master/src/Game.hs https://github.com/ivanperez-keera/haskanoid/blob/master/src....