Skip to content

zero-dimensional arrays/references/boxes for Julia. Ref-killer

License

Notifications You must be signed in to change notification settings

JuliaArrays/ZeroDimensionalArrays.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ZeroDimensionalArrays

Build Status Package version Package dependencies PkgEval Aqua

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 with mutable struct
    • does not support setfield!, or mutating the element otherwise
    • isbits when the element is isbits
  • Box
    • declared with mutable struct
    • supports setfield! for mutating the element
    • acts as a reference to its element
  • BoxConst
    • declared with mutable struct
    • does not support setfield!, or mutating the element otherwise
    • acts as a reference to its element

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 vs Base.RefValue by offering a replacement that makes Ref 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 entire struct into a mutable struct)
        struct SomeImmutableType
            immutable_bool::Bool
            immutable_float::Float64
            mutable_int::Box{Int}
        end
    • previous discussion:
  • To provide a boxing feature, for example for data deduplication to avoid excessive memory use. Either Box or BoxConst 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:
      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
      The other types, Box or BoxConst would work for this use case, too, as would any zero-dimensional array, but ZeroDimArray is more likely to have zero cost for performance.
    • previous discussion regarding Ref:

Comparison with other potential solutions

  • Zero-dimensional Array:
    • fill(x), creating a zero-dimensional Array containing x as its element, is often used instead of Ref(x).
    • Array{T, 0} where {T} is very similar to Box, albeit less efficient. The inefficiency is due to the fact that the implementation of Array supports resizeability (even though that's currently only available to users in the one-dimensional case of Vector), implying extra indirection, leading to extra pointer dereferences and extra allocation.
  • FixedSizeArrays.jl:
    • Less heavy than Array, but still may be less efficient than Box.
  • FillArrays.jl:
    • Zero-dimensional Fill, constructible with Fill(x), is equivalent to ZeroDimArray.

About

zero-dimensional arrays/references/boxes for Julia. Ref-killer

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages