5 ms·
I haven’t ever understood the argument against static typing. I’ve never declared a variable and not simultaneously thought “this is going to be a float, always
by sjwright 6y ago
I haven’t ever understood the argument against static typing. I’ve never declared a variable and not simultaneously thought “this is going to be a float, always a float, never not a float.”
The only exception to this is untrusted input, but for that an string is usually always fine.
- pansa2 6y ago> I’ve never declared a variable and not simultaneously thought “this is going to be a float, always a float, never not a float.” Never written generic/template code? Making that much easier is one of the main benefits of dynamic typing.
- viraptor 6y agoChange it to "this variable is always going to be a T, never not a T" and it still stands.
- sjwright 6y agoIt's possible—nay likely—that I don't understand the true value of generics. It's something that I've looked into on occasion and it never seemed all that useful to me. Most examples I've come across in the past were C++ and seemed like formalised workarounds for deficiencies in the C++ type system rather than being actually useful. I'm sure I've failed to grok them—or based on the code I write I'm not the target audience for them. I have no problem when a language allows the programmer to explicitly opt for a variable to be an undefined/dynamic type, whether as part of generics or as part of a defensive ingest of untrusted data. I admit this is previously unspecified nuance but in my mind this doesn't break my rule: "this variable is always going to be a dynamic type, never not a dynamic type." This means you know when to interact with it defensively. The thing I'd like in a hybrid static-dynamic language is type assertion blocks which restore some benefits of static typing while dealing with dynamic typed variables. E.g.: declare x as dynamic; x = untrusted_source(); if (x IS_A string) { // Inside here, x behaves as a statically typed string. // The compiler knows it and checks types appropriately. // Passing x elsewhere will send a static typed string. function_that_demands_a_string(x); } else if (x CAN_SAFELY_BECOME_A uint) { // True for any non-negative integer regardless of data type. // Inside here, x is always a statically typed uint. // If it was some other type, it was converted for me. } (This probably already exists in some language somewhere but my familiarity with languages is narrow.)
- ezrast 6y agoCrystal does some of what you want: https://tio.run/##ZVDBbsIwDL33KywmrRcaUXbbhHbeaYdpJ4RQaA1kCkllO6Ps57skBalshyQv7z3bT27owqLtMLS4h@CEAgu2W/aBGiwA1vEAzDSwkHGH2Tz/63p812VfzqG8pOun3IxkVS8Wqo5wo1ifOosFurYoGquZ4X33hY1EMc0TumzFb8PTMhcSSiAHjDZFsRjtCStC7rxrOXpf4XlSsMODcRndFau7ntwEvHqSmGEKNN45Wr1QYk7I0PpI97D6twk1iRotjWaEPoLzER185NXkxl0Qhl6FLjlu@uebk2ucUYfHCuolwEOMdwhWE1RA2nBM4B34b6S99eeXZDMMckQ4k@66OASixsa7W@s/u9kbYpkGuRFoGae83vFkAcPwCw https://tio.run/##ZVDBbsIwDL33KywmrRcaUXbbhHbeaYdpJ4RQaA1kCk... Note how the language is pretty smart about flow-typing variables as you narrow down their types. `x` here is typed as a tagged union (String | Int32 | Array(Char) | Float64 | UInt32), but by the time the program gets to the final `else` the compiler has figured out that the String and Array cases have already been dealt with (even though we never mentioned Array by name, just asked if the object implements a method that only Array implements), so it lets us call `x.abs`, which only works for numeric types. Of course, `abs` has different implementations for Int32 and Float64, but the signatures are compatible so the compiler lets it fly, resorting to dynamic dispatch at runtime. The missing part is that there's nothing like a CAN_SAFELY_BECOME_A operator so I had to implement that test myself (as `try_to_u32`) and call it early to get the flow typing to work. The Wikipedia article for the concept is https://en.wikipedia.org/wiki/Flow-sensitive_typing https://en.wikipedia.org/wiki/Flow-sensitive_typing
- sjwright 6y agoThat's very cool. And especially thanks for surfacing the Wikipedia article.
- dragonwriter 6y agoPython typecheckers (both pyright and mypy, I believe) do this (isinstance checks and some other checks in conditionals narrow the type on the defended path.)
- mekkkkkk 6y agoThe main benefit of generics is to easily maintain strong type information for implementers. With a <T>createMapWithStringKey(T arg) -> Map<string, T> You can keep strong type info with AType a var b = createMapWithStringKey<AType>(a) // b is for certain a Map<string, AType>