@@ -516,20 +516,47 @@ impl<T, const N: usize> [T; N] {
516516 ///
517517 /// # Note on performance and stack usage
518518 ///
519- /// Unfortunately, usages of this method are currently not always optimized
520- /// as well as they could be. This mainly concerns large arrays, as mapping
521- /// over small arrays seem to be optimized just fine. Also note that in
522- /// debug mode (i.e. without any optimizations), this method can use a lot
523- /// of stack space (a few times the size of the array or more).
524- ///
525- /// Therefore, in performance-critical code, try to avoid using this method
526- /// on large arrays or check the emitted code. Also try to avoid chained
527- /// maps (e.g. `arr.map(...).map(...)`).
528- ///
529- /// In many cases, you can instead use [`Iterator::map`] by calling `.iter()`
530- /// or `.into_iter()` on your array. `[T; N]::map` is only necessary if you
531- /// really need a new array of the same size as the result. Rust's lazy
532- /// iterators tend to get optimized very well.
519+ /// Note that this method is *eager*. It evaluates `f` all `N` times before
520+ /// returning the new array.
521+ ///
522+ /// That means that `arr.map(f).map(g)` is, in general, *not* equivalent to
523+ /// `array.map(|x| g(f(x)))`, as the former calls `f` 4 times then `g` 4 times,
524+ /// whereas the latter interleaves the calls (`fgfgfgfg`).
525+ ///
526+ /// A consequence of this is that it can have fairly-high stack usage, especially
527+ /// in debug mode or for long arrays. The backend may be able to optimize it
528+ /// away, but especially for complicated mappings it might not be able to.
529+ ///
530+ /// If you're doing a one-step `map` and really want an array as the result,
531+ /// then absolutely use this method. Its implementation uses a bunch of tricks
532+ /// to help the optimizer handle it well. Particularly for simple arrays,
533+ /// like `[u8; 3]` or `[f32; 4]`, there's nothing to be concerned about.
534+ ///
535+ /// However, if you don't actually need an *array* of the results specifically,
536+ /// just to process them, then you likely want [`Iterator::map`] instead.
537+ ///
538+ /// For example, rather than doing an array-to-array map of all the elements
539+ /// in the array up-front and only iterating after that completes,
540+ ///
541+ /// ```
542+ /// # let my_array = [1, 2, 3];
543+ /// # let f = |x: i32| x + 1;
544+ /// for x in my_array.map(f) {
545+ /// // ...
546+ /// }
547+ /// ```
548+ ///
549+ /// It's often better to use an iterator along the lines of
550+ ///
551+ /// ```
552+ /// # let my_array = [1, 2, 3];
553+ /// # let f = |x: i32| x + 1;
554+ /// for x in my_array.into_iter().map(f) {
555+ /// // ...
556+ /// }
557+ /// ```
558+ ///
559+ /// as that's more likely to avoid large temporaries.
533560 ///
534561 ///
535562 /// # Examples
0 commit comments