New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
function support on 0.5+ #137
Conversation
This is huge! #57 was probably one of the biggest issues of JLD since v0.5. https://github.com/JuliaIO/JLD.jl/blob/master/src/JLD.jl#L853 It's not immediately apparent to me why v0.4 would end up with more generic functions than v0.5, or at least, why this would be an issue Travis would have on v0.4 but not v0.5. |
https://travis-ci.org/JuliaIO/JLD.jl/jobs/202743914#L1519 sub needs to be view, but that looks unrelated. |
Could this get a review? |
I tried this out and I got an error: using JLD
JLD.save("out.jld","sol",sol2)
cannot write a pointer to JLD file
in h5type(::JLD.JldFile, ::Type{Ptr{Void}}, ::Bool) at jld_types.jl:287
in h5fieldtype(::JLD.JldFile, ::Any, ::Bool) at jld_types.jl:351
in JLD.JldTypeInfo(::JLD.JldFile, ::SimpleVector, ::Bool) at jld_types.jl:41
in h5type(::JLD.JldFile, ::Any, ::Bool) at jld_types.jl:367
in #write_compound#21(::Array{Any,1}, ::Function, ::JLD.JldGroup, ::String, ::SymEngine.Basic, ::JLD.JldWriteSession) at JLD.jl:705
in _write(::JLD.JldGroup, ::String, ::SymEngine.Basic, ::JLD.JldWriteSession) at JLD.jl:698
in write_ref(::JLD.JldFile, ::SymEngine.Basic, ::JLD.JldWriteSession) at JLD.jl:667
in h5convert_array(::JLD.JldFile, ::Array{SymEngine.Basic,1}, ::JLD.JldDatatype, ::JLD.JldWriteSession) at JLD.jl:611
in #_write#17(::Array{Any,1}, ::Function, ::JLD.JldGroup, ::String, ::Array{SymEngine.Basic,1}, ::JLD.JldWriteSession) at JLD.jl:574
in _write(::JLD.JldGroup, ::String, ::Array{SymEngine.Basic,1}, ::JLD.JldWriteSession) at JLD.jl:572
in write_ref(::JLD.JldFile, ::Array{SymEngine.Basic,1}, ::JLD.JldWriteSession) at JLD.jl:667
in macro expansion at jld_types.jl:669 [inlined]
in h5convert!(::Ptr{UInt8}, ::JLD.JldFile, ::LotkaVolterra, ::JLD.JldWriteSession) at jld_types.jl:685
in #write_compound#21(::Array{Any,1}, ::Function, ::JLD.JldGroup, ::String, ::Function, ::JLD.JldWriteSession) at JLD.jl:709
in _write(::JLD.JldGroup, ::String, ::Function, ::JLD.JldWriteSession) at JLD.jl:698
in write_ref(::JLD.JldFile, ::Function, ::JLD.JldWriteSession) at JLD.jl:667
in macro expansion at jld_types.jl:669 [inlined]
in h5convert!(::Ptr{UInt8}, ::JLD.JldFile, ::DiffEqBase.ODEProblem{Array{Float64,1},Float64,true,LotkaVolterra,Void,UniformScaling{Int64}}, ::JLD.JldWriteSession) at jld_types.jl:685
in #write_compound#21(::Array{Any,1}, ::Function, ::JLD.JldGroup, ::String, ::DiffEqBase.ODEProblem{Array{Float64,1},Float64,true,LotkaVolterra,Void,UniformScaling{Int64}}, ::JLD.JldWriteSession) at JLD.jl:709
in _write(::JLD.JldGroup, ::String, ::DiffEqBase.ODEProblem{Array{Float64,1},Float64,true,LotkaVolterra,Void,UniformScaling{Int64}}, ::JLD.JldWriteSession) at JLD.jl:698
in write_ref(::JLD.JldFile, ::DiffEqBase.ODEProblem{Array{Float64,1},Float64,true,LotkaVolterra,Void,UniformScaling{Int64}}, ::JLD.JldWriteSession) at JLD.jl:667
in macro expansion at jld_types.jl:669 [inlined]
in h5convert!(::Ptr{UInt8}, ::JLD.JldFile, ::DiffEqBase.ODESolution{Array{Array{Float64,1},1},Void,Void,Array{Float64,1},Array{Array{Array{Float64,1},1},1},DiffEqBase.ODEProblem{Array{Float64,1},Float64,true,LotkaVolterra,Void,UniformScaling{Int64}},OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.InterpolationData{LotkaVolterra,Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.Tsit5Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,1},OrdinaryDiffEq.Tsit5ConstantCache{Float64,Float64}}}}, ::JLD.JldWriteSession) at jld_types.jl:685
in #write_compound#21(::Array{Any,1}, ::Function, ::JLD.JldFile, ::String, ::DiffEqBase.ODESolution{Array{Array{Float64,1},1},Void,Void,Array{Float64,1},Array{Array{Array{Float64,1},1},1},DiffEqBase.ODEProblem{Array{Float64,1},Float64,true,LotkaVolterra,Void,UniformScaling{Int64}},OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.InterpolationData{LotkaVolterra,Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.Tsit5Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,1},OrdinaryDiffEq.Tsit5ConstantCache{Float64,Float64}}}}, ::JLD.JldWriteSession) at JLD.jl:709
in #write#14(::Array{Any,1}, ::Function, ::JLD.JldFile, ::String, ::DiffEqBase.ODESolution{Array{Array{Float64,1},1},Void,Void,Array{Float64,1},Array{Array{Array{Float64,1},1},1},DiffEqBase.ODEProblem{Array{Float64,1},Float64,true,LotkaVolterra,Void,UniformScaling{Int64}},OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.InterpolationData{LotkaVolterra,Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.Tsit5Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,1},OrdinaryDiffEq.Tsit5ConstantCache{Float64,Float64}}}}, ::JLD.JldWriteSession) at JLD.jl:524
in (::JLD.##35#36{String,DiffEqBase.ODESolution{Array{Array{Float64,1},1},Void,Void,Array{Float64,1},Array{Array{Array{Float64,1},1},1},DiffEqBase.ODEProblem{Array{Float64,1},Float64,true,LotkaVolterra,Void,UniformScaling{Int64}},OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.InterpolationData{LotkaVolterra,Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.Tsit5Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,1},OrdinaryDiffEq.Tsit5ConstantCache{Float64,Float64}}}},Tuple{}})(::JLD.JldFile) at JLD.jl:1279
in #jldopen#11(::Array{Any,1}, ::Function, ::JLD.##35#36{String,DiffEqBase.ODESolution{Array{Array{Float64,1},1},Void,Void,Array{Float64,1},Array{Array{Array{Float64,1},1},1},DiffEqBase.ODEProblem{Array{Float64,1},Float64,true,LotkaVolterra,Void,UniformScaling{Int64}},OrdinaryD... This was for a DiffEq solution, which is an overloaded type which does not |
Ok, so if I understand this correctly, this patch essentially saves an empty object of the given function's type. It saves no behavior. I suppose that's a nice analog to how it behaves for types; no methods get written alongside the data. My concern is with anonymous functions and accurately communicating to the user what actually is being saved — it's essentially just the name of the function. So this breaks badly with anonymous functions:
|
Yes, that's tricky. I think it would be OK, at least as a first pass, to simply say that anonymous functions aren't supported. Unfortunately I don't know of a way to tell whether a function is anonymous, for the sake of throwing an early error. Serialising functions for parallelism has essentially the same problem; I think in that case it just serialises functions from |
I suppose we could use the name of the function or function type. Seems super hacky, but any names beginning with |
It could cause issues with gensym functions, though only in the slightly pathological case where you use a number as the id: julia> gensym("1")
Symbol("##1#656")
julia> typeof(() -> ())
##1#2 |
https://github.com/MikeInnes/BSON.jl See also here for the anonymous functions issue (I haven't addressed this yet in BSON.jl, but plan to). |
BSON looks cool! Maybe you could add a line or two to the README about its status and plans. So, saving functions which are defined works (editing Matt's example from above #137 (comment)) :
but undefined ones don't work:
but you mean to address this, correct? |
Sort of, although I'm not planning to support named functions, only anonymous ones (i.e.
Any particular requests? It more or less is what it says on the tin at this stage. I'll let you know if I come up with any BSON-based plans for world domination :) |
Yes, anonymous function support would be awesome!
I meant whether it's ready for use, alpha, beta, etc. |
Ah I see. It should be ready to use for things it works with; more advanced types (e.g. Julia internal objects) might break it but it works for some fairly complex objects I've used it with (Flux models). |
fixes #57. Due to the broken type serialisation I've had to find a way to escape non-identifier symbols such that they are parseable.
I kept 0.4 compatibility; the old function storage type is still readable so this should be fully backwards-compatible.