JLD.jl icon indicating copy to clipboard operation
JLD.jl copied to clipboard

Deserializing DefaultDict fails

Open maximsch2 opened this issue 8 years ago • 4 comments

using DataStructures, JLD
d = DefaultDict(Int, Int, () -> 0)
d[1] = 3
@save "test.jld" d
@load "test.jld"

gives me

`DefaultDict{Int64,Int64,Function}` has no method matching DefaultDict{Int64,Int64,Function}()
while loading In[1], in expression starting on line 5

which is expected in the retrospect, but hopefully we can do better.

  1. At the very least, it will be very useful to warn about serializing types that I won't be able to get back afterwards. I've found this issue a week after I've saved the file and now I don't have a way to actually load that .jld file, knowing that in advance would've been helpful.
  2. Seeing how (de)serializing functions might be hard, maybe it makes sense to automatically covert DefaultDict to just Dict. It is certainly a local hack that won't fix other similar cases, but it will make the life a little bit easier.

maximsch2 avatar Aug 17 '15 23:08 maximsch2

The issue here is not with serializing functions, but with how JLD deals with Associatives. JLD assumes that all Associatives can be recovered completely from their keys and values, and serializes only these keys and values, rather than the internal representation of each Associative, in order to avoid dependence on the Associative's hash function. This works fine for Dicts or DataStructures.HashDicts, but doesn't make sense for DefaultDicts, which are defined not only by their keys and values, but also by their default functions/values.

In fact, wrapping Associatives in this manner will lead to problems for any Associatives which are defined by additional information other than their keys and values. One such example is the PriorityQueue found in Base.Collections, which depends not only on keys and values, but also the ordering. For example, the following code:

using Base.Collections, JLD
pq = PriorityQueue(Base.Order.Reverse)
pq["a"]=1
pq["b"]=2
pq["c"]=3

@save "pq.jld" pq
@load "pq.jld"

yields the error in Julia 0.4:

ERROR: MethodError: `convert` has no method matching convert(::Type{Base.Collections.PriorityQueue{Any,Any,Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}}}, ::Base.Order.ForwardOrdering)
This may have arisen from a call to the constructor Base.Collections.PriorityQueue{Any,Any,Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}}(...),
since type constructors fall back to convert methods.

Given these issues, I think it makes the most sense to change JLD so that only Dicts are wrapped, as opposed to all Associatives. Doing a quick search through Base, it looks like Dict is the only Associative that implements a hash function anyways. @TimHoly, what do you think?

amack315 avatar Oct 02 '15 05:10 amack315

@amack315, I'd be fine with changes in this direction that fix problems. Don't have time to work on that myself, though.

timholy avatar Oct 29 '15 10:10 timholy

Any update on this? I just ran into this problem.

tlnagy avatar Apr 11 '17 22:04 tlnagy

I also just ran in to this.

ghazel avatar Apr 16 '18 20:04 ghazel