Same function name in multiple modules?


#1

I would like to name a function draw in multiple modules. (My graph theory module would have a draw from drawing graphs, my hyperbolic geometry module would have a draw for drawing things in the hyperbolic plane, and so forth.) At times, I’d like to have a few modules loaded at the same time, but Julia tells me that the name is already taken. I thought, thanks to multiple dispatch, that as long as the argument types are different, this is possible. But I’m having trouble. Suggestions on how to achieve this please?


#2

You need to extend the draw method in the same way as you extend Base.getindex for example (prefix with module name to the module that defined the actual function that the rest of the modules extend).

If all methods that happened to have the same name automatically got merged, that would be kinda chaos.


#3

Two options: If you want them to be completely unrelated functions that happen to share the name draw, just use the qualified names:

import A, B
A.draw()
B.draw()

On the other hand, if they are supposed to be part of a family of related functions, so that you can have functions from module C that act on objects from A or B generically, e.g. a function foo(x) = (dosomething(x); draw(x)) that can act on an x from A or B, then the modules have to know about one another. In this case, as @kristoffer.carlsson says above, you need to extend a common draw function in A and B:

module A
using GenericDraw # first module where draw is defined
...
GenericDraw.draw(x::Atype) = ...
end

module B
using GenericDraw # first module where draw is defined
...
GenericDraw.draw(x::Btype) = ...
end

Then both A and B are defining different methods of the same draw function, dispatched by types defined in those modules.


#4

Thanks, but I’m not understanding. Could I have a Master module that just defines:

function draw()
end

And then modules A, B, and so on with

import Master: draw
function draw(x::Atype) .... end

in module A, and likewise in B and C. Or do I have no choice but to use A.draw(...) and B.draw(...) and so on.

I thought with multiple dispatch I could have lots and lots of functions named draw so long as their arguments were different types.


#5

Very helpful. I think I’ve got it. THANK YOU!


#6

Yes, you could do that.

A generic function has some “higher level concept” that we extend with other types. For example, let’s look at the docstring for push!

help?> push!
search: push! pushfirst! push pushfirst pushdisplay

  push!(collection, items...) -> collection

  Insert one or more items at the end of collection.

If you extend Base.push! then you opt into the “contract” that is specified by the function docstring. By doing so we can write generic code that works for many types of collections.

However, let’s say you are writing a game or something where you have a method called push! which pushes another player. Then you should not extend Base.push! because this function has a completely different meaning. There is no way to write generic code with Base.push! and your game version of push!.

So presumably, your draw function in the “Master” module has some higher level concept of drawing associated with it. Then you extend that function using Master.draw with other types that agree to that concept and we can write generic code using that draw function.