A tiny software package for the Julia programming language, providing zero-dimensional array types. Ref
-killer.
Exports these zero-dimensional subtypes of AbstractArray
, differing on topics such as mutability and identity:
ZeroDimArray
- declared with
struct
, not withmutable struct
- does not support
setfield!
, or mutating the element otherwise isbits
when the element isisbits
- declared with
Box
- declared with
mutable struct
- supports
setfield!
for mutating the element - acts as a reference to its element
- declared with
BoxConst
- declared with
mutable struct
- does not support
setfield!
, or mutating the element otherwise - acts as a reference to its element
- declared with
Any zero-dimensional array is an iterator containing exactly one element (this follows from the zero-dimensional shape). Ref
, too, is a zero-dimensional iterator, however it's not an array. Even though Ref
supports being indexed like a zero-dimensional array is commonly indexed, without an index: x[]
.
The motivation for creating this package is:
- To prevent the frequent confusion regarding
Ref
vsBase.RefValue
by offering a replacement that makesRef
unnecessary in many use cases. Previous discussion: - To provide "mutable wrapper" functionality:
Box
can be a good choice. Examples:- make a
const
binding that's mutable:const some_const_binding = Box(0.2)
- make a field within an immutable
struct
mutable (warning: it's usually more efficient to change the entirestruct
into amutable struct
)struct SomeImmutableType immutable_bool::Bool immutable_float::Float64 mutable_int::Box{Int} end
- make a
- previous discussion:
- To provide a boxing feature, for example for data deduplication to avoid excessive memory use. Either
Box
orBoxConst
might be a good choice here, depending on whether mutability is desired. Compare:-
julia> large_data = ntuple(identity, 8) (1, 2, 3, 4, 5, 6, 7, 8) julia> for _ ∈ 1:4 large_data = (large_data, large_data) end julia> Base.summarysize(large_data) 1024 julia> Base.summarysize([large_data for _ ∈ 1:1000]) # duplicates `large_data` a thousand times 1024040 julia> using ZeroDimensionalArrays julia> large_data_reference = Box(large_data); julia> Base.summarysize([large_data_reference for _ ∈ 1:1000]) # `large_data` isn't stored inline 9064
-
- To provide a wrapper type for treating a value as a scalar in broadcasting:
ZeroDimArray
can be a good choice:The other types,julia> using ZeroDimensionalArrays julia> isa.([1,2,3], [Array, Dict, Int]) 3-element BitVector: 0 0 1 julia> isa.(ZeroDimArray([1,2,3]), [Array, Dict, Int]) # now escape the vector from broadcasting using `ZeroDimArray` 3-element BitVector: 1 0 0
Box
orBoxConst
would work for this use case, too, as would any zero-dimensional array, butZeroDimArray
is more likely to have zero cost for performance.- previous discussion regarding
Ref
:
- Zero-dimensional
Array
:fill(x)
, creating a zero-dimensionalArray
containingx
as its element, is often used instead ofRef(x)
.Array{T, 0} where {T}
is very similar toBox
, albeit less efficient. The inefficiency is due to the fact that the implementation ofArray
supports resizeability (even though that's currently only available to users in the one-dimensional case ofVector
), implying extra indirection, leading to extra pointer dereferences and extra allocation.
- FixedSizeArrays.jl:
- Less heavy than
Array
, but still may be less efficient thanBox
.
- Less heavy than
- FillArrays.jl:
- Zero-dimensional
Fill
, constructible withFill(x)
, is equivalent toZeroDimArray
.
- Zero-dimensional