5 ms·
rustc sadly comes to a screeching halt when anything is done with generics. I seriously don‘t understand the obsession with naming generics „T“, „X“ or „Z“. Sin
by j-krieger 6y ago
rustc sadly comes to a screeching halt when anything is done with generics. I seriously don‘t understand the obsession with naming generics „T“, „X“ or „Z“. Single character variables have been declared bad since the 60s, why hasn‘t the same happened for generic type parameters?
- creata 6y agoDo you have an example of where single-letter type parameters lead to confusion? I haven't seen one yet.
- deleted 6y ago[deleted]
- Omin 6y agoThis Rust function has badly chosen single-letter type parameters that confused someone on my team recently: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.map_err https://doc.rust-lang.org/stable/std/result/enum.Result.html... Result<T,E> uses T for a generic contained value and E for another generic contained value that should be an error. So far so good. The `map_err` method then uses F for the new error type because it's just next alphabetically to E and uses O for the closure it accepts as parameter because F is taken. Usually, F is used for function arguments. F and O are not just non-descriptive, having F not be the function when there's a function argument is actively misleading. Instead of `F`, something like `NEW_E` or `NEW_ERROR` would have been much easier to understand.
- duckerude 6y agoBecause there's often only one or two type parameters in scope, and then disambiguating them isn't too hard. It can still get confusing, especially in unfamiliar code, but it's not on the same level as ordinary identifiers.
- idolaspecus 6y agoIn my experience it's because of two things mostly. (1) Naming generics is harder than naming other variables for whatever reason. (2) Signatures with generics in them are stupidly long. Signatures with generics tend to be super unaesthetic, and oftentimes unaesthetic code is conflated (correctly or incorrectly) with bad code.
- agumonkey 6y agoIt's a math culture thing. Names barely matter, relationships do. All math since junior high is about f(x), not function_of(variable_entity). It's very disturbing from the application Dev world view where people seek longer names for reasons, but after spending time in FP/LP and math you quickly forget long names. You seek variable count reduction most the time also.
- ywei3410 6y agoThis comment hits the nail on the head - if you think in terms of expressions and subsequently, expression substitution; there sometimes /is/ no good name for something. This is /especially/ true for abstract code - functions like identity, const, map.
- ulucs 6y agoMore accurately, math is about f:X->Y which is almost Haskell syntax
- j-krieger 6y agoI understand where you're coming from. The problem is when using multiple generic Parameters, rustc outputs something like this: `the trait 'Factory<_, _, _>' is not implemented for 'fn(Json<Auth>)' -> impl std::future::Future {auth}”. What is this error saying? Can you tell? I certainly can't
- mjburgess 6y agoI haven't programmed in Rust... but presumably it's just looking for an instance of that trait for that type? It seems the type here is a function from JSON to a Future? Given Factory means Factory, then, its saying there's no way to create an instance of that function?
- agumonkey 6y agoAre you annoyed / confused because of <_,_,_> ? It seems rust compiler team didn't write a proper error message or I cannot find meaning in this .. usually _ means 'whatever type' but <_,_,_> is useless if all types are the same whatever.
- Spivak 6y agoFor the same reason we still use i,j,k for loops, x and y for continuous variables, and n,m for integers. We all know what they mean and needless verbosity can makes things less readable. It’s why people really seem to like the throwaway variable ‘_’. for outer_index over array1 for inner_index over array1[outer_index] print array1[outer_index][inner_index] Bleh.
- floxy 6y agoProbably because it gets harder to name things as they get more abstract and more generic? I'd be interested to see your three favorite examples. Or I guess those would be the most obnoxious examples.
- akersten 6y agoI would contend that single letter names for generics are the ideal state. They're intentionally not given a meaningful name, because if you can give them a meaningful name, you've modelled the data wrong. IMO, if you're giving a generic a name beyond T, Z, etc. the logic probably isn't really generic, and should be a concrete implementation instead.
- p1necone 6y agoFor single param generic types I'd agree - i.e. with List<T> it's perfectly obvious what T is. But any generic with more than one type is obviously doing different things with each one and that needs to be explained. The obvious example would be a Map<Key, Value>. Now that I've typed that out though it kinda seems that List<Value> would be clearer, if not for the years of getting used to List<T> being the standard. You shouldn't be talking about the meaning of T from the consumers perspective, but you should be describing it at the level of abstraction that your generic code is operating at.
- dasyatidprime 6y agoI'm usually in favor of conciseness for one or two type parameters (much less so for any more than that), but if you do go full-words, “Value” is not much more descriptive than “T”, like writing “argument” instead of “x” for not much benefit. “Element” would be more descriptive of the role of the type parameter relative to the List type.
- j-krieger 6y agoI'm a fan of terseness when writing code myself, but I dislike terseness very when when it's sparsely documented code found in a library.
- akersten 6y agoTo touch on the Map example, I do think Map<K,V> is just as clear and saves keystrokes, so that's how I'd write it. The "meaning" of K,V doesn't come from their names, it comes from Map. I suppose clearer is a question of semantics, but to me there's not any more information conveyed by writing List<Value> vs List<T> - we already know T is a "Value" (because it has to be, due to List). The data structure itself should provide the needed context - if the base data structure is so complex that the meaning of its generic parameters isn't obvious, that may be a case where naming them makes sense... but to me it's also a code smell of square-peg-in-round-hole.