Inherit from Dict

219 views
Skip to first unread message

Michael Fox

unread,
Dec 1, 2013, 3:34:19 PM12/1/13
to julia...@googlegroups.com
It's common in Python for a class to inherit Dict. But how to do it in Julia? I wonder if it would be possible to use macro magic to emulate inheritance or even multiple inheritance.

type MyDict{K, V} <: Associative{K,V}
    d::Dict{K,V}
    other
    stuff

    function MyDict(; other="default_other", stuff="default_stuff")
        new(Dict(), other, stuff)
    end
end
MyDict(kv...; other="default_other", stuff="default_stuff") = Dict{Any, Any}(kv...)

# Test·

m = MyDict()
m = MyDict(; other="my_other", stuff="my_stuff")
m = MyDict({"B"=>2})
m = MyDict({"B"=>2}; other="my_other", stuff="my_stuff")
m["a"] = 1
@show isempty(m)
@show keys(m)
@show m

Ivar Nesje

unread,
Dec 1, 2013, 3:56:49 PM12/1/13
to julia...@googlegroups.com
I suggested something like this in https://github.com/JuliaLang/julia/issues/4935#issuecomment-29310595, but I think Stefan had a pretty good reason for not allowing this because the memory layout would be different and you can't mix your MyDict with regular Dicts in a typed Array.

If you can't use your subtype of Dict in an Array{Dict,1}, the functions that takes a Dict and combines it with other dicts in such array will fail. You will get rules for determining what functions can be called with MyDict instead of the regular Dict, and which functions who can't. Those rules will probably not be intuitive for users, and give unexpected results.

In writing this I wanted to suggest some sort of boilerplate reduction so that you could extend a type without having to copy the implementation of all the methods, but all my suggestions have major flaws.

Ivar

Steven G. Johnson

unread,
Dec 1, 2013, 4:08:41 PM12/1/13
to julia...@googlegroups.com
It should be possible to define a

@wrappertype WrapperT T field

macro that takes a type WrapperT with a field::T, and for each method defined for a type T (via methods_with) it defines a corresponding method acting on type WrapperT (unless method_exists says that the method already exists).

So, for example, you could define

type MyDict{K,V} :< Associative{K,V}
d::Dict{K,V}
end
@wrappertype MyDict Dict d

and it would create a drop-in replacement for Dict. This mechanism could even simulate some degree of multiple inheritance.

Ivar Nesje

unread,
Dec 1, 2013, 4:45:01 PM12/1/13
to julia...@googlegroups.com
Is it enough to recreate only the type specific methods or would we need to copy the generic methods too? As methods can access fields of a type without specifying the type in the signature, this can cause confusion and problems.

Just to make sure we talk about the same.
@wrappertype Dict MyDict d
Would expand to
keys(d::MyDict) = keys(d.d)
And so on...

Steven G. Johnson

unread,
Dec 1, 2013, 8:13:00 PM12/1/13
to julia...@googlegroups.com
It's pretty rare fir untyped generic methods to access internal fields of concrete types (I can think of only one example in the Julia standard library), and it seems like bad style except in very special cases.

Still, even if this occurs, the worst that is likely to happen is that an exception occurs, and you have to overload that method manually. The point of my suggested macro is that it would save a lot of manual labor, not necessarily all labor.

And once Julia gains the ability to overload the . operator, wrapper types can implement fall-through methods for field access too.

Stefan Karpinski

unread,
Dec 1, 2013, 7:29:51 PM12/1/13
to julia...@googlegroups.com
I'm not sure how well factored it is, but there is the Associative abstract type to inherit from.

Steven G. Johnson

unread,
Dec 1, 2013, 9:58:44 PM12/1/13
to julia...@googlegroups.com
Stefan, the associative abstract type is not enough if you want to build off and extend the existing Dict implementation.

Kevin Squire

unread,
Dec 2, 2013, 12:02:57 AM12/2/13
to julia...@googlegroups.com
See https://github.com/JuliaLang/julia/pull/3292 for one a @delegate macro.  I've used something like this, and was happy enough with it, although it might need some tweaking.

https://github.com/JuliaLang/julia/issues/4935 also looks useful.  I've submitted an OrderedDict implementation as a pull request.  Moving many of the fields of Dict to an AbstractDict type would simplify things like OrderedDicts and might generally make "subclassing" Dicts easier.

As an aside, I just committed an DefaultDict implementation to the DataStructures.jl package.

Cheers, Kevin
Reply all
Reply to author
Forward
0 new messages