# Arithmetic ops for arrays / slices

**URL:** <https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553>\
**Category:** language design\
**Created:** [March 13, 2025, 4:04pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553 "2025-03-13T16:04:05Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [March 13, 2025, 4:04pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/1 "2025-03-13T16:04:05Z")

</div>

I found myself staring at a handwritten `fn xor_in_place` and wondering if there was anything built into the language to do it for me, and decided what I would really like is if in-place arithmetic were supported for core arrays. Something like:

```rust
impl<T: AddAssign, const N: usize> AddAssign for [T; N] {
     fn add_assign(&mut self, rhs: Self) {
        for (a, b) in self.iter_mut().zip(rhs) {
            *a += b;
        }
     }
}

```

...but for all the core arithmetic ops.

(note: that could probably be more general with respect to `Rhs`, just an example)

That would make it possible to do:

```rust
let mut x = [1, 2, 3];
let y = [4, 5, 6];    
x += y;

```

> **[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=d9643de6b273a3c8075506c550648a8d)**
>
> A browser interface to the Rust compiler to experiment with the language

It seems like similar functionality could be added to slices as well, although there are a lot more decisions there like how to handle length mismatches.

* * *

Edit: I chose to use `AddAssign` as an example but upon further reflection that might not be the greatest place to start due to questions about e.g. overflow handling.

Bitwise operations seem a little more straightforward and that's really my main use case.

I originally opened this as "in-place" operations but there's no reason that e.g. `BitAnd`/`BitOr`/`BitXor` couldn't be supported as well, so I removed "in-place" from the title.

---

<div class="post-metadata">

**Author:** ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)\
**Post date:** [March 13, 2025, 6:33pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/2 "2025-03-13T18:33:26Z")

</div>

Rust is not Fortran or Matlab; element-wise arithmetic on arrays is not nearly common enough a use case to justify adding these IMO. Arrays just aren’t arithmetic types in Rust, and the meaning of arithmetic ops would be non-obvious. These operations are much more suitable to a third-party vector type that wraps arrays.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [March 13, 2025, 6:45pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/3 "2025-03-13T18:45:05Z")

</div>

Hmm, this already works: [https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=a624cf437790f77949f92195edf7c83f](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=a624cf437790f77949f92195edf7c83f)

```rust
let mut x = [1, 2, 3];
let y = [4, 5, 6];
std::iter::zip(&mut x, &y).for_each(|(a, b)| a.add_assign(b));
dbg!(x);

```

Which isn't bad at all.

I wonder if there's a place for something to simplify the tuple-to-separate-arguments step, like how there's `tuple` and `untuple` in functional languages.

If it was just (since [`u32: AddAssign<&u32>`](https://doc.rust-lang.org/std/primitive.u32.html#impl-AddAssign%3C%26u32%3E-for-u32))

```rust
std::iter::zip(&mut x, &y).for_each_pair(AddAssign::add_assign);

```

or

```rust
std::iter::zip(&mut x, &y).for_each(tupled(AddAssign::add_assign));

```

or something that might be fine.

* * *

As a meta-point, the other problem with these operators on arrays is that they're _eager_. And like how `array::map` warns about it, you don't really want `x * y + z` on _arrays_ to be eager that way, because once the array gets long it'll codegen poorly.

What you really want is a way to separate the transformer from the iterator chain, so you can build a transformer that represents the `_ * _ + _`, then apply that element-wise to the inputs. Ideally in a way that the transformer could be used both for things like arrays but also for iterators too.

(I have no idea what such an API would look like, though.)

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [March 13, 2025, 9:55pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/4 "2025-03-13T21:55:25Z")

</div>

> [@scottmcm](#):
>
> What you really want is a way to separate the transformer from the iterator chain, so you can build a transformer that represents the `_ * _ + _`, then apply that element-wise to the inputs. Ideally in a way that the transformer could be used both for things like arrays but also for iterators too.

This reminds me of what [Eigen](https://eigen.tuxfamily.org/index.php?title=Main_Page) in C++ does. It basically uses a lot of [template black magic](https://eigen.tuxfamily.org/dox/TopicLazyEvaluation.html) to delay the concrete evaluation until an assignment is made to a concrete vector or matrix type. With it being C++ it does of course come with footguns, around self assignments and aliasing (and it is up to the user to keep this in mind).

I haven't had the need to look at linear algebra since I learned rust, so I don't know if the Rust libraries also does things like that (or if Rust generics are even capable of expressing this).

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [March 14, 2025, 7:42am UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/5 "2025-03-14T07:42:14Z")

</div>

> [@Vorpal](#):
>
> or if Rust generics are even capable of expressing this

Rust's iterators are expression templates (the pattern behind Eigen): the type builds up a series of operations to calculate on the sequence and doesn't make a concrete type until an appropriate API is called. Futures are also expression templates for that matter. However, as with iterators, the problems arise when one needs to _name_ the types on the boundaries of APIs. In C++, this means using Eigen and `auto` can end up with some…funky error messages (the same problem comes up with `auto` and the proxy types used by `std::vector<bool>`).

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [March 14, 2025, 12:11pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/6 "2025-03-14T12:11:58Z")

</div>

> [@mathstuf](#):
>
> In C++, this means using Eigen and `auto` can end up with some…funky error messages

That is nothing new for C++ though. 1000s of lines of errors due to a small typo is par for the course.

But it sounds like good news, the pattern should work in Rust (if any library implements it for matrices etc I don't know).

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [March 14, 2025, 12:18pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/7 "2025-03-14T12:18:27Z")

</div>

I'm afraid that on slices this could make error messages worse, or even cause run-time errors (from mismatched len) when people accidentally mix up scalars and arrays.

The set of operations supported by overloads is limited. There's already `array.map`. Perhaps `array.zip` should exist too?

I'm also concerned that eager evaluation (that includes `.map` and potential `.zip`) can be a performance footgun.

It would be nice to have an iterator-like interface. Unfortunately the `Iterator` is not great at working with fixed-length sets, and `FromIterator` can't make an array. Can `Iterator`/`FromIterator` be fixed? Would it be worth adding some kind of `FixedLenIterator` for arrays?

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [March 14, 2025, 5:47pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/8 "2025-03-14T17:47:09Z")

</div>

> [@kornel](#):
>
> Would it be worth adding some kind of `FixedLenIterator` for arrays?

I think the main point here is that you _can't_ have a fixed length version of anything with a `next(&mut self)`, because it's fundamentally not fixed-length. It needs to be more `IntoIterator` that has the fixed length, though [back in 2018](https://github.com/rust-lang/rust/pull/48544) libs-api wasn't interested on a size hint for the current `IntoIterator`, at least.

> [@kornel](#):
>
> Perhaps `array.zip` should exist too?

It used to, but was removed: [Remove array\_zip by workingjubilee · Pull Request #112096 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/pull/112096)

It's not that useful when it's eager, because reifying the array of pairs is almost never what you want. Perhaps a `zip_map` could work, though.

> [@kornel](#):
>
> It would be nice to have an iterator-like interface.

What I'm imagining is that you still have an iterator-like interface, but you do it over abstract "sources" of some kind, rather than over a particular input iterator. In the scalar version, that's like the classic "compose" combinator that takes `T->U` and `U->V` giving `T->V`, but which arguably is essentially the same as a combining two `Iterator::Map`s.

So you'd build up some `impl Transformer` (I have no idea what the trait bounds on it would be). Then you could always pass iterator(s) to that to get out iterators, but also if it implements `KnownLengthTransformer` then there's a way to pass array(s) to it and get array(s) out.

(Well, it might need to be `LengthPreservingTransformer` for now, because we can't do `[T; N] -> [U; {N * Self::MULTIPLIER}]` in the current state of what constant generic expressions are allowed to do.)

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [March 16, 2025, 9:29pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/9 "2025-03-16T21:29:35Z")

</div>

I think I may have confused the issue by proposing all arithmetic ops.

The bitwise ops are the ones I actually cared about here and generally sidestep most of the problems that have been raised, especially in regard to working in special arithmetic forms to allow for various forms of lazy evaluation.

(For what its worth I maintain elliptic curve libraries that use projective coordinates to defer inversions as well as lazy field operations that defer reductions for exactly those purposes. For things like linear combinations though, we use dedicated APIs)

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [March 17, 2025, 12:43am UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/10 "2025-03-17T00:43:01Z")

</div>

> [@bascule](#):
>
> The bitwise ops are the ones I actually cared about here

TBH then do you actually need _generic_ operations on arrays, or just bigger integer types? Suppose you could just `u<512>` and do bitops on that...

---

<div class="post-metadata">

**Author:** ![DragonDev1906](https://avatars.discourse-cdn.com/v4/letter/d/e68b1a/32.png) [@DragonDev1906](https://internals.rust-lang.org/u/DragonDev1906)\
**Post date:** [March 17, 2025, 10:47am UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/11 "2025-03-17T10:47:54Z")

</div>

How about something like `element_wise!{x += y}`? That would be expressive and could allow more complex expressions. Though implementing it as a macro could be more difficult than expected, at least if more complex expressions should be supported. Something similar could be useful for `unchecked_*`, `wrapping_*`, ... methods on integers: `unchecked!{a + b - c} * 7` (using a macro to not need a new keyword), making larger chains of these methods more readable: `a.unchecked_add(b).unchecked_sub(c) * 7`.

Though doing this as a (decl.) macro would be really difficult if other code should be allowed to be part of the block. For example to just set the default way to be used for things like `a + b`.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [March 18, 2025, 1:29pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/12 "2025-03-18T13:29:21Z")

</div>

Yeah, I've had `zip_map` in mind when I said `zip`.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [September 9, 2026, 1:30pm UTC](https://internals.rust-lang.org/t/arithmetic-ops-for-arrays-slices/22553/13 "2026-09-09T13:30:18Z")

</div>

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
