# Wrapper type of static array, how to expose iterator

**URL:** https://discourse.julialang.org/t/wrapper-type-of-static-array-how-to-expose-iterator/118124
**Category:** General Usage
**Tags:** parametric-types, staticarrays
**Created:** [August 13, 2024, 8:41am UTC](https://discourse.julialang.org/t/wrapper-type-of-static-array-how-to-expose-iterator/118124 "2024-08-13T08:41:39Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![NatMath](https://avatars.discourse-cdn.com/v4/letter/n/4491bb/32.png) [@NatMath](https://discourse.julialang.org/u/NatMath)
#### Post date: [August 13, 2024, 8:41am UTC](https://discourse.julialang.org/t/wrapper-type-of-static-array-how-to-expose-iterator/118124/1 "2024-08-13T08:41:39Z")

</div>

I’m working on a raytracer where I need a `Point` type, which is just a wrapper over `StaticArray` that has different properties when transformed than a vector. My current implementation is as follows:

```julia
struct Point{N, T<:Number}
    p::SVector{N, T}
end; export Point

Point{N}(p::Vector{T}) where {N, T<:Number} = Point{N, T}(SVector{N, T}(p))
Point{N}(coords::T...) where {N, T<:Number} = Point{N, T}(SVector{N, T}(coords...))

iterate(point::Point) = iterate(point.p)
iterate(point::Point, state) = iterate(point.p, state)
.
.
.
lastindex(X::Point) = lastindex(X.p)
similar(::Point{N, T}) where {N, T} = zero(SVector{N, T})

```

Where I defined all the methods in the iterator and indexing interfaces to call down to `p`.  
However, whenever I use broadcasting on a `Point`, the wrapper is lost, such that `Point(SVector(1., 2.)) .+ 1 isa Vector{Float64}`.

My two questions are

1. Why is the return type of the broadcast a `Vector`, and not `SVector`?
2. How do I correctly write the wrapper such that I can broadcast over a `Point` and get a new `Point` out?

Thanks

---

<div class="post-metadata">

### Author: ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)
#### Post date: [August 13, 2024, 9:02am UTC](https://discourse.julialang.org/t/wrapper-type-of-static-array-how-to-expose-iterator/118124/2 "2024-08-13T09:02:27Z")

</div>

Broadcasting is not iteration. There is a section in the manual about interfaces which handles broadcasting: [Interfaces · The Julia Language](https://docs.julialang.org/en/v1.10/manual/interfaces/#man-interfaces-broadcasting)

Perhaps you missed that?

---

<div class="post-metadata">

### Author: ![NatMath](https://avatars.discourse-cdn.com/v4/letter/n/4491bb/32.png) [@NatMath](https://discourse.julialang.org/u/NatMath)
#### Post date: [August 13, 2024, 9:07am UTC](https://discourse.julialang.org/t/wrapper-type-of-static-array-how-to-expose-iterator/118124/3 "2024-08-13T09:07:16Z")

</div>

Thank you. I was under the impression that broadcasting was implemented over iteration.

---

<div class="post-metadata">

### Author: ![NatMath](https://avatars.discourse-cdn.com/v4/letter/n/4491bb/32.png) [@NatMath](https://discourse.julialang.org/u/NatMath)
#### Post date: [August 13, 2024, 2:03pm UTC](https://discourse.julialang.org/t/wrapper-type-of-static-array-how-to-expose-iterator/118124/4 "2024-08-13T14:03:07Z")

</div>

Here’s my working solution for anyone stumbling here. Based on [this other discourse post](https://discourse.julialang.org/t/custom-broadcasting-for-static-immutable-type/69426). The main issue I had is the documentation doesn’t describe how to implement broadcasting for immutable types, such as when the backing vector is a `SVector`.

```julia
struct Point{N, T<:Number} <: AbstractArray{T, 1}
    p::SVector{N, T}
end; export Point

# Broadcasting
import Base.broadcastable
Base.broadcastable(point::Point) = point
struct PointStyle{N} <: Broadcast.BroadcastStyle end
import Base.Broadcast.BroadcastStyle 
Base.Broadcast.BroadcastStyle(::Type{Point{N,T}}) where {N,T} = PointStyle{N}()
Base.Broadcast.BroadcastStyle(::PointStyle{N}, ::Broadcast.DefaultArrayStyle{0}) where N = PointStyle{N}()
import Base.Broadcast.materialize
function Base.Broadcast.materialize(B::Broadcast.Broadcasted{PointStyle{N}}) where N
    flat = Broadcast.flatten(B)
    args = flat.args
    f = flat.f
    ps = map(x -> x isa Point ? x.p : Ref(x), args)
    Point(f.(ps...))
end

```

---

<div class="post-metadata">

### Author: ![NatMath](https://avatars.discourse-cdn.com/v4/letter/n/4491bb/32.png) [@NatMath](https://discourse.julialang.org/u/NatMath)
#### Post date: [August 14, 2024, 8:20am UTC](https://discourse.julialang.org/t/wrapper-type-of-static-array-how-to-expose-iterator/118124/5 "2024-08-14T08:20:18Z")

</div>

I have since run into an issue with this. Doing `p .+ 1` works, however `p .^ 2` did not. Changing the line `ps = map(x -> x isa Point ? x.p : Ref(x), args)` to just `ps = map(x -> x isa Point ? x.p : x, args)` (no `Ref`) fixes this. Is this the normal way to do this, or would this introduce further bugs?
