Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

map SOneTo to SVector #1032

Open
tpapp opened this issue Jun 1, 2022 · 6 comments
Open

map SOneTo to SVector #1032

tpapp opened this issue Jun 1, 2022 · 6 comments

Comments

@tpapp
Copy link
Contributor

tpapp commented Jun 1, 2022

Issue

julia> using StaticArrays

julia> map(i -> (a = i, b = i + 1), axes(SVector(1, 2, 3), 1))
3-element MVector{3, NamedTuple{(:a, :b), Tuple{Int64, Int64}}} with indices SOneTo(3):
 (a = 1, b = 2)
 (a = 2, b = 3)
 (a = 3, b = 4)

is an MVector, while intuitively (and perhaps incorrectly?) I expected an SVector.

Versions

(@v1.8) pkg> st StaticArrays
Status `~/.julia/environments/v1.8/Project.toml`
  [90137ffa] StaticArrays v1.4.4 `~/.julia/dev/StaticArrays`

julia> VERSION
v"1.8.0-beta3"

though discussion in #855 suggests this has been around for a while.

@tpapp
Copy link
Contributor Author

tpapp commented Jun 1, 2022

Looking at the code, I was wondering if using signatures of the type

mapreduce(f, op, a::Union{SOneTo,StaticArray}, b::Union{SOneTo,StaticArray}...)

would fix this. (The approach of #978 would make this slightly cleaner, instead of hardcoding a concrete type.)

I will wait for comments then make a PR.

@jishnub
Copy link
Member

jishnub commented Jun 10, 2022

This is consistent with Base, though, isn't it?

julia> map(i -> (a = i, b = i + 1), Base.OneTo(3))
3-element Vector{NamedTuple{(:a, :b), Tuple{Int64, Int64}}}:
 (a = 1, b = 2)
 (a = 2, b = 3)
 (a = 3, b = 4)

In this case, given a statically sized axis, we obtain a statically sized mutable vector.

@tpapp
Copy link
Contributor Author

tpapp commented Jun 10, 2022

The issue for me is getting SVectors. I am not sure that the interface of Base implies anything about this, map doesn't say anything about the result being mutable, so it is up to this package to decide what to do here.

Generally, I found find it consistent if map(f, ...immutable types defined in this package...) would return an SArray. But that's just a personal preference.

@jishnub
Copy link
Member

jishnub commented Jun 10, 2022

I understand, and I do agree that this could be made allocation-free. However, if you specifically want an SVector, you should probably wrap the result in one instead of relying on the return type of map.

@tpapp
Copy link
Contributor Author

tpapp commented Nov 6, 2023

Revisiting this issue: I agree that one should wrap in SVector. But currently SVector(SOneTo(x)) fails, with

ERROR: The size of type `SVector` is not known.

Would it make sense to have have a conversion method, eg along the lines of

SVector::SOneTo{N}) where N = SVector(ntuple(identity, Val(N)))

@tverho
Copy link

tverho commented Nov 4, 2024

I'm occasionally quite annoyed by this behavior. Maybe a partial solution would be to provide a similar constructor as Tensors.Vec: e.g. Vec{N}(i->i^2). This is very similar to ntuple(i->i^2, N). In other words, of these three, SVector is the only one that doesn't offer a clean way to do this (I can think of map(i->i^2, SVector{N}(1:N)) or @SVector [i^2 for i in 1:N], neither of which are pretty).

So basically I'm proposing a constructor SVector{N}(f::Function). Maybe that would create the expectation to have also SArray{Tuple{N,M,...)}((i,j,...)->function(i,j,...)).

A related issue is that sum(function, SOneTo(N)) won't produce the same allocation-free code as sum(function, SVector{N}(1:N)), because there's no specialization in mapreduce for SOneTo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants