Search code examples
templatestypesjuliadispatch

Julia function signatures and sub-types, specifically String, ByteString


(Using Julia 0.3.11) I'm having trouble type-annotating correctly some of my code, in an initial version we've been using ASCIIString - to annotate any String, to "avoid" abstract types, but let's start with the example, this might be related to what I've seen refereed to as "triangular dispatch" in some discussions here:

# How to type annotate this (sortof "Dictionary with default)
function pushval!(dict, key, val)
  key in keys(dict) ? push!(dict[key], val) : dict[key] = [val]
  return dict
end

d1 = Dict{ASCIIString, Vector{Int}}()
d2 = Dict{String, Vector{Int}}()

pushval!(d1, "a", 1)
pushval!(d2, "a", 1)

Ok (firstly - if there's a more idiomatic way to construct a dictionary with defaults, in this case an empty array, I'd love to hear about it)

So now, I've tried to type annotated it:

function pushval!{K, V} (dict::Dict{K, Vector{V}} , key, val)

Much more documenting, and works. But now comes the trickier part - I want 'key' to be any subtype of K, and val - any subtypes of V (right?) eg - I would like to make a dictionary of String - which is an abstract type, but use concrete keys - which are ASCIIString/ByteString/UTF8String,

I thought I should write one of the followings:

function pushval!{K, V} (dict::Dict{K, Vector{V}} , key::KK <: K, val:: VV <: V)
function pushval!{K, V, KK <: K, VV <: V} (dict::Dict{K, Vector{V}} , key::KK, val::VV)

One solution would be as suggest in ( Can I use a subtype of a function parameter in the function definition? ) something with 'convert'.

But this whole thing made me wonder about the Julia code I'm writing, I've started a write a system - using String, FloatingPoint, Number and such abstract types, when I actually tried running it, I've reverted to convert everything to concrete types just to get thing running for now...

Is there a recommended codebase to read as a reference to idiomatic Julia code? Like the very implementation of Julia's dictionary-assign operator even. Is there a part of the standard library considered good to start with as a reference? thanks


Solution

  • I know this is only partly what you asked for, but maybe you find it sufficient.

    What you call pushval! can be achieved using push!(get!(d1, "a", []), 1) (although it will return the dictionary value that was appended to instead of the dictionary itself). If you need to constrain the type of the inner collection's values, you can, for example, use:

    push!(get!(d1, "a", Number[]), 1)
    

    If you really need to define this as a function, I am afraid that, at the moment, you cannot define the types in the way you describe. As the accepted answer to the question you referenced notes, Julia does not implement triangular dispatch yet, although it is targeted for 0.5.