Skip to content

Commit 6854803

Browse files
committed
Implement SA[...] syntax for SArray literals
Upside: This gives extremely attractive syntax for short static array literals. Downside: This is a syntax pun: the result of the `SA[...]` depends on whether the name `SA` is bound to `StaticArrays.SA` or is local variable of some other type. However, this is no worse than Int[1,2,3], which is also a pun on the array indexing syntax. Cases where this syntax could refer to something other than StaticArrays.SA are detectable by the compiler and in principle also accessible to a linter.
1 parent 1e580d5 commit 6854803

File tree

4 files changed

+59
-0
lines changed

4 files changed

+59
-0
lines changed

src/StaticArrays.jl

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export SHermitianCompact
3636

3737
export Size, Length
3838

39+
export SA
3940
export @SVector, @SMatrix, @SArray
4041
export @MVector, @MMatrix, @MArray
4142

@@ -113,6 +114,7 @@ include("SizedArray.jl")
113114
include("SDiagonal.jl")
114115
include("SHermitianCompact.jl")
115116

117+
include("initializers.jl")
116118
include("convert.jl")
117119

118120
include("abstractarray.jl")

src/initializers.jl

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
SA[ array initializer ]
3+
4+
A type for initializing static array literals using array construction syntax.
5+
Returns an `SVector` or `SMatrix`.
6+
7+
# Examples:
8+
9+
* `SA[x, y]` creates a length-2 SVector
10+
* `SA[a b; c d]` creates a 2×2 SMatrix
11+
* `SA[a b]` creates a 1×2 SMatrix
12+
"""
13+
struct SA ; end
14+
15+
Base.getindex(::Type{SA}, xs...) = SVector(xs)
16+
Base.typed_vcat(::Type{SA}, xs::Number...) = SVector(xs)
17+
Base.typed_hcat(::Type{SA}, xs::Number...) = SMatrix{1,length(xs)}(xs)
18+
19+
Base.@pure function _SA_hvcat_transposed_type(rows)
20+
M = rows[1]
21+
if any(r->r != M, rows)
22+
# @pure may not throw... probably. See
23+
# https://discourse.julialang.org/t/can-pure-functions-throw-an-error/18459
24+
return SMatrix{-1,-1}
25+
end
26+
SMatrix{M,length(rows)}
27+
end
28+
29+
@inline function Base.typed_hvcat(::Type{SA}, rows::Dims, xs::Number...)
30+
mtype = _SA_hvcat_transposed_type(rows)
31+
if mtype === SMatrix{-1,-1}
32+
throw(ArgumentError("SA[...] matrix shape inconsistent"))
33+
end
34+
# hvcat lowering is row major ordering, so must transpose
35+
transpose(mtype(xs))
36+
end
37+
38+

test/initializers.jl

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
SA_test_ref(x) = SA[1,x,x]
2+
@test @inferred(SA_test_ref(2)) === SVector{3,Int}((1,2,2))
3+
@test @inferred(SA_test_ref(2.0)) === SVector{3,Float64}((1,2,2))
4+
5+
SA_test_vcat(x) = SA[1;x;x]
6+
@test @inferred(SA_test_vcat(2)) === SVector{3,Int}((1,2,2))
7+
@test @inferred(SA_test_vcat(2.0)) === SVector{3,Float64}((1,2,2))
8+
9+
SA_test_hcat(x) = SA[1 x x]
10+
@test @inferred(SA_test_hcat(2)) === SMatrix{1,3,Int}((1,2,2))
11+
@test @inferred(SA_test_hcat(2.0)) === SMatrix{1,3,Float64}((1,2,2))
12+
13+
SA_test_hvcat(x) = SA[1 x x;
14+
x 2 x]
15+
@test @inferred(SA_test_hvcat(3)) === SMatrix{2,3,Int}((1,3,3,2,3,3))
16+
@test @inferred(SA_test_hvcat(3.0)) === SMatrix{2,3,Float64}((1,3,3,2,3,3))
17+
@test @inferred(SA_test_hvcat(1.0im)) === SMatrix{2,3,ComplexF64}((1,1im,1im,2,1im,1im))
18+

test/runtests.jl

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ include("convert.jl")
3131
include("core.jl")
3232
include("abstractarray.jl")
3333
include("indexing.jl")
34+
include("initializers.jl")
3435
Random.seed!(42); include("mapreduce.jl")
3536
Random.seed!(42); include("arraymath.jl")
3637
include("broadcast.jl")

0 commit comments

Comments
 (0)