I am exploring whether I can get some oo behaviour (data inheritance) in Julia, but that is not my question today. In that exploration I have this code that, to my surprise, fails:
abstract type Family end
type Parent <: Family
a::Float64
end
type Child <: Family
a::Float64
parent::Parent
end
convert(::Type{Parent},x::Child) = x.parent
promote_rule(::Type{Child},::Type{Parent}) = Parent
combine(x::Parent,y::Parent) = print("Two Parents\n")
combine(x::T,y::T) where {T<:Family} = combine(x.parent,y.parent)
p = Parent(1.)
c = Child(3.,p)
combine(c,p)
The above fails. I expect Julia to use my promotion rule, convert Child to Parent, and thus call my second â€ścombineâ€ť method (which then calls the first â€ścombineâ€ť method.
No joy. Julia points out that there is no combine(::Child,::Parent) method. Where did I go wrong?
 You need to either import
convert
and promote_rule
or prefix with Base
:
Base.convert(::Type{Parent},x::Child) = x.parent
Base.promote_rule(::Type{Child},::Type{Parent}) = Parent
 Julia doesnâ€™t do implicit promotions, hence:
combine(x::Family, y::Family) = combine(promote(x, y)...)

julia> combine(c,p)
Two Parents
2 Likes
Thanks. I keep forgetting to import!!! Iâ€™ll use the module.Function syntax in the future, as you suggest.
No implicit promotion, thatâ€™s very important. But I made that mistake for a reason: still playing around, I programmed â€śdual numbersâ€ť (automatic differentiation). There I have
convert(::Type{Dual} ,x::Float64) = Dual(x,0.)
promote_rule(::Type{Dual} ,::Type{Float64) = Dual
+(a::Dual,b::Dual) = Dual(a.x+b.x, a.dx.+b.dx)
*(a::Dual,b::Dual) = Dual(a.x*b.x, a.dx.*b.x.+b.dx.*a.x)
(no explicit call to â€śpromoteâ€ť) and I can combine Float64 and Dualâ€¦
Itâ€™s not the first time I get great help from you
That is because of: https://github.com/JuliaLang/julia/blob/b3241d7845f136d1f400f7283ae37128250d2883/base/promotion.jl#L276
+(x::Number, y::Number) = +(promote(x,y)...)
*(x::Number, y::Number) = *(promote(x,y)...)
(x::Number, y::Number) = (promote(x,y)...)
/(x::Number, y::Number) = /(promote(x,y)...)
i.e. all numbers promote with +
, *
, 
, /
.
3 Likes
Thanks! I had writen an answer before you last post, but apparently did no â€śpress returnâ€ť:
Gosh am I slow!
Of course, somewhere in Julia there is something like
+(x,y) = +(promote(x,y)...)
which is why my â€śdualâ€ť code works while I need to promote in my â€śFamilyâ€ť code.
: )
1 Like