Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading a function in two files (in Julia)

I'm gonna explain my problem on a minimal example. Let's say I have three files:

A.jl

module A

export Atype, f

type Atype  
end

f = function(x::Atype)
    println("f called with A")
end
end #module

B.jl

module B

export Btype, f

type Btype  
end

f = function(x::Btype)
    println("f called with B")
end
end #module

Main.jl

 using A
 using B

 main = function()
    x = Atype()
    f(x)
 end

 main()

Here I have two versions of f function. If I understand the idea of the multiple dispatch correctly, it should be deducted during runtime which version should be used. Hence, I expected that running Main.jl would print f called with A. Unfortunately, I get

$ julia Main.jl 
ERROR: type: anonymous: in typeassert, expected Btype, got Atype
 in include at /usr/bin/../lib64/julia/sys.so
 in process_options at /usr/bin/../lib64/julia/sys.so
 in _start at /usr/bin/../lib64/julia/sys.so
while loading /home/grzes/julia_sucks/Main.jl, in expression starting on line 9

If I comment out using B, it works fine. Clearly, f from B.jl overwrote f from A.jl.

So, the question is: where does the problem lie? In my approach or in the version of Julia I use (0.3.7)? How can I circumvent this?

Note that replacing using A with import A and using fully qualified names (e.g. A.f) is not a good solution. It contradicts with the crux of multiple dispatch -- at compile time I don't know if I should use A.f or B.f.

like image 554
grześ Avatar asked Sep 01 '25 02:09

grześ


1 Answers

You have to make A.f and B.f the same function (in the example above they are just different functions with the same name). Then you can overload one method in each of the modules and multiple dispatch will do its job.

The way to achieve this is either to have one of the modules import the function f from the other (eg import A.f in B) before extending it with a new method, or adding a third module C with an f function that both A and B import (you can use a dummy signature like f(::Union()) = nothing that never applies to create a function without adding any real method). Our extend the function from the other module directly, as in

function A.f(x::Atype)
    println("f called with A")
end

This will make Julia understand that the two f refer to the same concept, and they will actually be the same object in both modules. Adding a method modifies the generic function object, so this change will be visible everywhere that f is used.

like image 53
Toivo Henningsson Avatar answered Sep 03 '25 17:09

Toivo Henningsson