SparseArray cannot store arbitrary type, but only types which support zero

I think this is a bug report to Julia, however I first would like to gather some thoughts.

Concretely, I cannot map over a SparseVector of Functions.

julia> a = SparseVector([1, 2])
2-element SparseVector{Int64, Int64} with 2 stored entries:
  [1]  =  1
  [2]  =  2

julia> fs = map(x -> y -> x+y, a)
2-element SparseVector{var"#32#34"{Int64}, Int64} with 2 stored entries:
  [1]  =  #32
  [2]  =  #32

julia> map(f -> f(1), fs)
ERROR: MethodError: no method matching zero(::Type{var"#32#34"{Int64}})
Closest candidates are:
  zero(::Union{Type{P}, P}) where P<:Dates.Period at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/Dates/src/periods.jl:53
  zero(::T) where T<:Dates.TimeType at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/Dates/src/types.jl:423
  zero(::AbstractIrrational) at irrationals.jl:148
  ...
Stacktrace:
 [1] _zeros_eltypes
   @ /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/SparseArrays/src/higherorderfns.jl:204 [inlined]
 [2] _noshapecheck_map(::var"#35#36", ::SparseVector{var"#32#34"{Int64}, Int64})
   @ SparseArrays.HigherOrderFns /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/SparseArrays/src/higherorderfns.jl:160
 [3] map(f::var"#35#36", A::SparseVector{var"#32#34"{Int64}, Int64})
   @ SparseArrays.HigherOrderFns /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/SparseArrays/src/higherorderfns.jl:143
 [4] top-level scope
   @ REPL[96]:1

Using julia 1.6.1

julia> versioninfo()
Julia Version 1.6.1
Commit 6aaedecc44 (2021-04-23 05:59 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, icelake-client)
Environment:
  JULIA_EDITOR = code-insiders
  JULIA_NUM_THREADS = 
I didn't read carefully :confused:

I’m not quite sure what you wanted to achieve but your map function essentially maps your entry to a function again. So your SparseVector now stores functions!

julia> a = SparseVector([1, 2])
2-element SparseVector{Int64, Int64} with 2 stored entries:
  [1]  =  1
  [2]  =  2

julia> fs = map(x -> (y -> "hello"), a)[1]("asdasdasdas")
"hello"

julia> fs = map(x -> (y -> "hello"), a)[1](42)
"hello"

But mapping over SparseVectors in principle works:

julia> map(x -> x^2, a)
2-element SparseVector{Int64, Int64} with 2 stored entries:
  [1]  =  1
  [2]  =  4

it is intended that it stores functions.

I was expecting that SparseVector can deal with ANY Julia type. Is there anywhere a documentation saying that this is intentionally not the case?

You’re right, I should read to the end :smiley:

See Sparse Arrays · The Julia Language

Sparse arrays are arrays that contain enough zeros that storing them in a special data structure leads to savings in space and execution time, compared to dense arrays.

1 Like

Probably you want a dictionary/map container (e.g. the built-in Dict in Julia), not a SparseVector.

1 Like

thanks a lot, that explains completely, why it expects zero to exist