6 ms·
It’s a small thing, but array::from_fn makes me happy.
by aendruk 4y ago
It’s a small thing, but array::from_fn makes me happy.
- svnpenn 4y agoWhy does it arbitrarily choose length 5? https://doc.rust-lang.org/core/array/fn.from_fn.html https://doc.rust-lang.org/core/array/fn.from_fn.html
- aendruk 4y agoIn that example N is inferred from the assertion; observing the output has affected it.
- svnpenn 4y agoWow that is stupid. That is way too much assumption.
- surewe 4y agoSure, it's a lot of assumption, but the type system would prevent an invalid assumption from compiling (arrays are typed [T; N] where T is the type they hold and N is the number of elements), and you can always override it with a turbofish.
- dymk 4y agohttps://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_sy... It's a dream once you understand it. You don't need to understand the math, just the general concept of type unification, and that type inference can flow in "both directions", as opposed to in e.g. C++ where `auto` inference only works in one direction. Rust is not exactly HM type inference, but it's something close to it. http://smallcultfollowing.com/babysteps/blog/2014/07/09/an-experimental-new-type-inference-scheme-for-rust/ http://smallcultfollowing.com/babysteps/blog/2014/07/09/an-e...
- chrismorgan 4y agoNo, it’s just the right amount, and makes perfect sense. This is the whole point of type inference: where there are multiple possibilities, determine types based on how you use them, and if you still have ambiguity after that, complain. If you tried comparing it to something that wasn’t an array, or if you tried comparing it to multiple different-sized arrays, it would complain.
- sophacles 4y agoExactly 0 assumptions are made - how is that too much?
- Tuna-Fish 4y agoThere is no assumption here, just type inference. If you want it to be more explicit, you could just decorate the declaration with a type.
- shepmaster 4y agoIs likely based on what you compare it to. For example, this passes as well let array = core::array::from_fn(|i| i); assert_eq!(array, [0, 1, 2, 3, 4, 5]); The magic of type inference
- brundolf 4y agoSomething I can't figure out is how it infers the length in this example: let array = core::array::from_fn(|i| i); assert_eq!(array, [0, 1, 2, 3, 4]); Is it because of the assert_eq? Can it use the length of the second argument to infer the length all the way back up in the from_fn call?
- aendruk 4y agoYep, you could change the asserted length and it would succeed: assert_eq!(array, [0, 1, 2]); If you tried both— assert_eq!(array, [0, 1, 2]); assert_eq!(array, [0, 1, 2, 3, 4]); —the assertions would never run because it wouldn’t even compile: error[E0277]: can't compare `[usize; 3]` with `[{integer}; 5]`
- dymk 4y agoYes, it's inferring that `array` must be an `[i32; 5]` because there exists an impl of `PartialEq` for `[T; N]` against another `[T; N]`, so `N` in `::from_fn` must be 5.
- brundolf 4y agoThat rocks
- zerr 4y agoWhat's a sane/legit use case of such inferring in general?
- brundolf 4y agoI think the one here is legit (perhaps more realistic would be where you're passing the new array to an actual function that requires a certain array length). People always complain about Rust's type system being verbose- well, this makes it less verbose. It knows what you need from the function call, so it doesn't make you say it. And as an added benefit, if the required type ever changes in a way that can still be generated by the provided code (eg. the function you're passing to needs a different length), you won't need to update any explicit type annotations at the call-site. If that's ever undesirable - you want to be very precise about your code - well, then you can do that too by specifying the generic parameters explicitly.