I’m assuming you mean to use SVector instead of SizedVector in my code.
Unfortunately doesn’t work.
As far as wrapping my vector into SVector to have a well-defined array length works… I’m creating something like… say My own package.
The user would have to then import StaticArrays.jl in order to use my functions, and that isn’t something I want.
Any way to do it without wrapping?
Any property of the Vector that we can take advantage of to identify the type?
1 thing we can do is say all right…
If length(Vector) == 2
do this
else
do that
end
or something along those lines. But just checking the web if there is some standard way to do this.
To give you an idea of what I’m up to…
If the user inputs a vector of len 2, I’ll set other attributes to those of a 2-dimensional object, and likewise for len = 3.
I don’t want the input to have to deal with a third package. Just simply input a Vector.
If you create a package and declare StaticArrays.jl as a dependency, this is transparent to the user. They don’t need to load that package themselves explicitly. But you’re right that it will be loaded implicitly. Are you worried about the weight of the dependency?
StaticArrays.jl is a really standard and optimized way of dealing with small vectors, typically 2d and 3d. If you’re worried about performance, I would suggest trying it out instead of rolling out your own solution.
This does not work, because [1,2,3] is a vector not a static vector. But StaticVector.jl has a nice short form of construction so
> typeof(SA[1,2,3]) <: SVector{3}
true
The simple reason is, that StaticArrays.jl does not overload the default vector constructor, since that would be a (very very heavy) type piracy). But the SA prefix makes code nearly as neat.
does work. To illustrate the dispatch I understood you want, take a look at
using StaticArrays
f(sa::SVector{2}) = "A"
f(sa::SVector{3}) = "B"
yields
julia> [f(SA[1,2]), f(SA[1,2,3])]
2-element Vector{String}:
"A"
"B"
Ahhhh so we pretty much have to use a third-party definition itself.
That was honestly something I didn’t want to do.
I like the way Makie lets you input anything to plot… Points, Tuples, Vectors, you name it!
Was thinking more like… without the user needing to think much, whatever type he/she feels comfortable working with in his/her particular use case, they can use that.
I guess this is it tho… SA functioning is all there is to use to have the functionality I want.
If you don’t want to require the user to explicitly import StaticArrays.jl just to create the arrays to put into your functions you can always eat the type-instability in the “interface layer” of your package. I mean something like:
# If the user provided a static array
f(sa::SVector{2}) = "A"
f(sa::SVector{3}) = "B"
# if the user provided a normal vector
f(v::Vector) = f(SVector{length(v)}(v)) # causes 1 dynamic dispatch
This is a very common design pattern in Julia. Most “setup” function in e.g. DifferentialEquations.jl contain type instabilities, e.g. when you ask DE to pick a reasonable default solver.
Edit: I am somewhat assuming, that you would use these vectors for some longer computation. If not, then you should just use if with branches I suppose.
The where you propose is not possible.
The main problem is that vectors can grow arbitrarily, so when they should keep track of their length to dispatch on (that is not calling length but more SA like) you have no other chance than wrapping that.
Makie internally definetly checks the length a few times, and I do agree, for user facing functions such flexibility is nice; however, internally, both for readability and code maintenance, the StaticArray approach is probably preferable (in my opinion it definelty is) – thesis basically what @abreamer proposes as well – for the user it is nice, they can still pass normal vectors.
Sure you can avoid third party code – by implementing such types yourself. In my experience, Julia is modular, which has the large advantage, that usually people more clever than me come up with solutions that I can nicely use (and avoid reinventing the wheel).
Well calling this function with a normal Array causes a dynamic dispatch, which comes with some performance penalty and causes a few memory allocations. As long as the user does not call this function in a tight inner loop that must be 100% efficient, it is fine. However, if performance is critical then the user can just switch to StaticArrays and everything is fine.
Hmmm…
I don’t think I’ll need to use it that often.
Honestly, I need it for like a fraction of a second lol.
I would take whatever input the user has and convert it to an Observable Point type for internal work.
So I just need this kind of mechanism to distinguish between 2-element and 3-element vectors during dispatch.
And there are only these 2 cases? Honestly, I’d just use a plain, boring if length(v) == 2. Everything else seems kinda over-engineered at this point. This also has the advantage that you don’t need to worry about anything with performance and it is as easy as it gets for the compiler.
using StaticArrays
# f(v::Vector) = f(SVector{length(v)}(v))
mutable struct P
x
# If the user provided a static array
f(v::Vector) = f(SVector{length(v)}(v))
function P(x::SVector{2})
new("A")
end
function P(x::SVector{3})
new("B")
end
end
this doesn’t work
I mean yeah, I guess this wont.
I do have some more questions tbh…
mutable struct P
x
function P(x::Vector)
if length(x) == 2
new("A")
elseif length(x) == 3
new("B")
else
throw(TypeError)
end
end
function P(x::SVector{2})
new("A")
end
function P(x::SVector{3})
new("B")
end
end
Is this efficient? Or is there any benefit for Multiple Dispatch for this use case?
This is literally all I would need (To be honest, with that little if statement, wouldn’t need to deal with static arrays in the first place)
I’ll just have an Additional set of definitions for Vectors. What say?
(sorry for pinning your but… @abraemer@kellertuer)
Well you have a f in there. That probably should have been P. Try:
mutable struct P
x
P(v::Vector) = P(SVector{length(v)}(v))
P(x::SVector{2}) = new("A")
P(x::SVector{3}) = new("B")
end
If you mean the construction, then I’d say yes.
Here the issue is more that the field is untyped which is generally bad for performance. However, this might not matter for your case and be a perfectly reasonable design choice. Runtime performance is not the only design goal after all
I agree: I don’t think it is reasonable to use StaticArrays.jl just for a singular dispatch with two options. So just ditch SA and keep the if.
All right I might sound crazy but I ran my personal benchmarks (using BenchmarkTools) multiple times and found that defining the types for structs in the Function is more efficient than defining them in the definition (if you get what I’m trying to convey).
Lol. Idk how true that is in general. But at least that’s what I found to be true for my Struct definitions.
Worked! Thank you!
Although, as you said, I feel it’s not worth using Static Arrays. Might be better to use an If statement.
However, would still put your code as the answer to the Question I had! Thank you!!
Thank you @abraemer and @gdalle for your help too!
No I don’t really get what you mean, but feel free to open a new topic and post the benchmark code. Putting types in the place where you use some untyped field of a struct might recover some performance, but generally typed fields should be as fast as it gets. So you likely had a small mistake in your benchmark.
But as I said: If performance is not critical or less important than simplicity of the implementation, then you don’t need to put types on fields in your struct.
All right just decided, that using StaticArrays.jl is simpler and convenient instead of literally reiterating everything.
I would have had to do something like
If something isa Vector
do something
for everything.
I had 2 dispatches, 1 more 2D, 1 for 3D.
I just added the f(v::Vector) = f(StaticArray) thingy for my Struct, Added StaticArray{} in the Union for my defining function arguments and now everything works incredibly well.
hmmm… does lose a bit on the speed but that isn’t that bad I’d say… (4x the time taken)
I mean for the user, who just has to define things once and for all and then just use Observables to control things thereafter, that doesn’t matter if?
As for internal definitions, I’ll be sure to Use the Quickest method.