Hello all,

Apologies in advance if I’m missing something obvious. I’ve only just started 
experimenting with some of the more advanced features of Julia’s types, and 
I’ve hit a bit of a wall…

Say I wanted to replicate something like Python’s `collections.defaultdict` or 
Ruby’s `Hash` class with a default value. So far this is what I have:

——8<——8<——

    immutable DefaultDict{K, V} <: Associative{K, V}
      default::V
      dict::Dict{K, V}
    end
    
    function DefaultDict(val)
      return DefaultDict(val, Dict())
    end
    
    function Base.getindex{K, V}(dd::DefaultDict{K, V}, key::K)
      if haskey(dd.dict, key)
        getindex(dd.dict, key)
      else
        dd.default
      end
    end

——8<——8<——

Ideally, I’d like to avoid having to re-implement all of the methods one would 
expect `Dict` to work with, since I can trivially convert from a `DefaultDict`:

——8<——8<——

    Base.convert(::Type{Associative}, dd::DefaultDict) = dd.dict
    Base.promote_rule(::Type{Associative}, ::Type{DefaultDict}) = Associative

——8<——8<——

However, this doesn’t seem to work as I had hoped it might:

——8<——8<——

    > foo = DefaultDict(42)
    > foo['a'] = 1
    ERROR: MethodError: `setindex!` has no method matching 
setindex!(::DefaultDict{Any,Any}, ::Int64, ::Char)
    Closest candidates are:
      setindex!(::Associative{K,V}, ::Any, ::Any, ::Any, ::Any…)

——8<——8<——

Sure, implementing `setindex!`, `length`, `start`, etc. would be trivial, but 
I’m more worried about third-party code that expects `Dict` arguments. In 
principle I’d like to still be able to pass instances of `DefaultDict` to 
methods that would otherwise expect `Dict`s.

Am I completely off-base with this approach? What’s the most “Julian” solution 
to specializing types in this manner?

Cheers,

Josh

Reply via email to