# Broadcasting across array of SVectors

**URL:** <https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573>\
**Category:** New to Julia\
**Created:** [March 19, 2021, 10:30pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573 "2021-03-19T22:30:47Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)\
**Post date:** [March 19, 2021, 10:30pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/1 "2021-03-19T22:30:47Z")

</div>

I have an array of S-vectors and I want to do something like:

```julia
b .%5

```

and perform the `mod` across all elements of each vector. So I built this:

```julia
function Base.rem(x::SVector{Float64},y::Float64)::SVector{Float64}
SVector(x[1]%y,x[2]%y)
end

```

and it didn’t work. It wasn’t until I modified it to be like:

```julia
function Base.rem(x::SArray{Tuple{2},Float64,1,2},y::Float64)::SArray{Tuple{2},Float64,1,2}
SVector(x[1]%y,x[2]%y)
end

```

that it worked for me. So I guess my question is exposing my lack of understanding of types. When I declare a variable to be an SVector, I do it like this:

```julia
vec:: SVector{2,Float64}

```

so why is the type different for the function definition I tried above? The issue is more general than just “How do I mod over an array of SVectors?” because I got it working. I think I just need help understanding types in general. (Yes, I’ll re-read the documentation on that too.)

Any thoughts or ideas to share?

Secondary question: Could I define `rem` so that it would take an SVector of any length?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 19, 2021, 10:42pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/2 "2021-03-19T22:42:34Z")

</div>

> [@lancejnelson](#):
>
> `function Base.rem(x::SVector{Float64},y::Float64)::SVector{Float64}`

That’s not what what the `SVector` type signature looks like — it is parameterized by _two_ numbers, the length of the vector and the type of the elements. Since your code only works for an `SVector` with two elements, you could do: `x::SVector{2,Float64}`, for example.

But you seem to be making it much more complicated than necessary. Why not just do:

```julia
myrem(x::SVector, y::Number) = x .% y

```

which will do the elementwise `%` that you want for any number of elements and any types? (I wouldn’t advise overloading `Base.rem`, since that’s [type piracy](https://docs.julialang.org/en/v1/manual/style-guide/#Avoid-type-piracy).)

(Realize that argument-type declarations and return-type declarations do _nothing_ for performance here. Even with no argument-type declarations at all, Julia will compile a specialized version of the function for any argument types you pass. And it will infer the return type on its own.)

---

<div class="post-metadata">

**Author:** ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)\
**Post date:** [March 19, 2021, 10:43pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/3 "2021-03-19T22:43:10Z")

</div>

Hmm. OK, after playing a little bit I can see that this:

```julia
function Base.rem(x::SArray{T},y::Float64)::SArray{T} where {T}
SVector(map(x -> x%y,x))
end

```

works too and will work for vectors of any length. So, I think I’m confused about knowing how to declare a type correctly. How many arguments go inside the `{}` and how can I figure that out?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 19, 2021, 10:45pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/4 "2021-03-19T22:45:18Z")

</div>

> [@lancejnelson](#):
>
> How many arguments go inside the `{}` and how can I figure that out?

The number (and kinds) of type parameters depends on the type. You have to look at the documentation (or the source code if there are no docs).

For example, this type has no parameters:

```julia
struct Foo
    x::Float64
    y::Float64
end

```

This has one parameter:

```julia
struct Bar{T}
    x::T
    y::T
end

```

and this has two parameters:

```julia
struct Baz{T,S}
    x::T
    y::S
end

```

In the case of StaticArrays, `SVector{n,T}` is a simplified alias for `SArray{Tuple{n},T,n}`, where `T` is the element type and `n` is the number of elements.

---

<div class="post-metadata">

**Author:** ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)\
**Post date:** [March 19, 2021, 10:47pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/5 "2021-03-19T22:47:58Z")

</div>

So why does this work:

```julia
function Base.rem(x::SVector,y::Float64)::SVector
SVector(map(x -> x%y,x))
end

```

Shouldn’t I be required to specify the type and number of elements in the type declaration?

---

<div class="post-metadata">

**Author:** ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)\
**Post date:** [March 19, 2021, 10:48pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/6 "2021-03-19T22:48:55Z")

</div>

> [@stevengj](#):
>
> I wouldn’t advise overloading `Base.rem` , since that’s [type piracy](https://docs.julialang.org/en/v1/manual/style-guide/#Avoid-type-piracy).)

Noted. Thank you. I guess I was just hoping to use the `%` operator instead of a custom function. But I see your points

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 19, 2021, 10:49pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/7 "2021-03-19T22:49:35Z")

</div>

> [@lancejnelson](#):
>
> Shouldn’t I be required to specify the type and number of elements in the type declaration?

No. Any trailing type parameters that you omit can be anything.

`x::SVector` means that `x` can be `SVector{n,T}` for any `n` and `T`. `x::SVector{2}` means that `x` can be an `SVector{2,T}` for any `T`.

---

<div class="post-metadata">

**Author:** ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)\
**Post date:** [March 19, 2021, 10:50pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/8 "2021-03-19T22:50:47Z")

</div>

Got it. Thanks for taking the time to school a newb. Much appreciated.

---

<div class="post-metadata">

**Author:** ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)\
**Post date:** [March 30, 2021, 8:40pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/9 "2021-03-30T20:40:31Z")

</div>

So is this type piracy?

```julia
struct Squares
    count::Int
end

Base.iterate(S::Squares, state=1) = state > S.count ? nothing : (state*state, state+1)

```

If it is, what is the best way to build a custom iterator? If not, why not?

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [March 30, 2021, 8:46pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/10 "2021-03-30T20:46:29Z")

</div>

It’s only type piracy if you define iteration for types you don’t “own”. This example is fine because you own `Squares`. The previous one, was redefining an operation in `Base` for `Struct`s defined in `StaticArrays`.

---

<div class="post-metadata">

**Author:** ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)\
**Post date:** [March 30, 2021, 8:59pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/11 "2021-03-30T20:59:36Z")

</div>

I think I got it. So it’s type piracy even though there didn’t exist an operation in Base with type StaticArrays.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 30, 2021, 9:36pm UTC](https://discourse.julialang.org/t/broadcasting-across-array-of-svectors/57573/12 "2021-03-30T21:36:38Z")

</div>

Yes, because the function (`rem`) is from `Base` and the type (`SVector`) is from `StaticArrays`. So, if you did write this method in a package and someone loaded it, or you loaded a third-party package, and such package relied either in `rem` failing for `SVector`, or `rem` calling a generic fallback that allowed for `SVector` (like a fallback for `AbstractVector`), the third-party package could start acting differently, what is considered spooky-action-at-a-distance and a bad practice.
