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

unthunk `getindex` and `iterate` on `Composite` objects

Open gxyd opened this issue 5 years ago • 8 comments

Fixes #233

gxyd avatar Oct 17 '20 15:10 gxyd

Currently something like:

julia> r = Composite{Tuple{Float64,}}(a=(@thunk 2.0^2), b=(@thunk 2.0^3))
julia> collect(r)
MethodError: Cannot `convert` an object of type 
  Float64 to an object of type 
  Thunk
Closest candidates are:
  convert(::Type{T}, !Matched::T) where T at essentials.jl:171
  Thunk(::F) where F at /Users/gaurav/.julia/dev/ChainRulesCore/src/differentials/thunks.jl:95

Stacktrace:
 [1] setindex!(::Array{Thunk,1}, ::Float64, ::Int64) at ./array.jl:826
 [2] copyto!(::Array{Thunk,1}, ::Composite{Tuple{Float64},NamedTuple{(:a, :b),Tuple{Thunk{var"#3#5"},Thunk{var"#4#6"}}}}) at ./abstractarray.jl:724
 [3] _collect(::UnitRange{Int64}, ::Composite{Tuple{Float64},NamedTuple{(:a, :b),Tuple{Thunk{var"#3#5"},Thunk{var"#4#6"}}}}, ::Base.HasEltype, ::Base.HasLength) at ./array.jl:609
 [4] collect(::Composite{Tuple{Float64},NamedTuple{(:a, :b),Tuple{Thunk{var"#3#5"},Thunk{var"#4#6"}}}}) at ./array.jl:603
 [5] top-level scope at In[12]:1

raises error. Would that need re-defining Base.collect as well?

gxyd avatar Oct 18 '20 09:10 gxyd

Though as expected collect(Float64, r) works just fine:

julia> collect(Float64, r)
2-element Array{Float64,1}:
 4.0
 8.0

I'll add the test case for it.

gxyd avatar Oct 18 '20 10:10 gxyd

Hi @nickrobinson251 can you please review this :)

gxyd avatar Oct 20 '20 10:10 gxyd

julia> r = Composite{Tuple{Float64,}}(a=(@thunk 2.0^2), b=(@thunk 2.0^3))
julia> collect(r)
MethodError: Cannot `convert` an object of type 
  Float64 to an object of type 
  Thunk

I think this is because we are now defining the eltype wrong. Rather than special casing collect, we might need to special case HasEltype so that if the composite backing type has thunks, it says that it is EltypeUnknown. This is more involved than i thought.

We should probably also have tests of something that uses iterate more directly than collect. Maybe a little function for a for loop?

oxinabox avatar Oct 20 '20 13:10 oxinabox

What about something like:

julia> a = Composite{Tuple{Thunk}}((@thunk 2.0^3), (@thunk 2.0^2))

Is it supposed to give unthunked values on iteration?

gxyd avatar Oct 25 '20 08:10 gxyd

What about something like:

julia> a = Composite{Tuple{Thunk}}((@thunk 2.0^3), (@thunk 2.0^2))

Is it supposed to give unthunked values on iteration?

Yes. (Assuming you mean Tuple{Thunk, Thunk} since two arguments) Though Tuple{Thunk, Thunk} is a super weird primal type. I'm note sure if it should even occur during second order differentiation.

But since a Thunk at the end of the day actually represents the value it returns on being unthunked, and should be operated on as such, it is always correct and desirable to unthunk it before manipulating it

oxinabox avatar Oct 25 '20 10:10 oxinabox

Rather than special casing collect, we might need to special case HasEltype so that if the composite backing type has thunks, it says that it is EltypeUnknown

Did you mean to say, special casing Base.IteratorEltype? Even Base.HasEltype don't accept any arguments to it.

gxyd avatar Oct 25 '20 14:10 gxyd

Did you mean to say, special casing Base.IteratorEltype?

Yes

oxinabox avatar Nov 20 '20 19:11 oxinabox