Implementing a function from an interface, multiple dispatch

I am reading the source of CSVFiles.jl and I see it implements the TableTraits interface, which in Julia, is the defacto way of describing table data. I see functions like

function TableTraits.getiterator(file::CSVFile)
    res = _loaddata(file)
    it = TableTraitsUtils.create_tableiterator([i for i in res[1]], [Symbol(i) for i in res[2]])
    return it
end 

I noticed TableTraits.getiterator rather than just getiterator. I am a bit confused on why the name is prepended with TableTraits. I thought multiple dispatch didn’t require this? And that it would pick the right getiterator based on the types it gets. In this particular case, if someone was to call getiterator(mycsvfile::CSVFile), this function should be called. Do we need the prepend, and if so why?

Follow up question… suppose I have my own custom type and that I’d like a “pretty print” of this type in the repl. Would It not be sufficient to define show(io, MyType) or do I have to define Base.show(io, MyType)?

In Julia, there may be many functions with the same name in different modules, and each function may have multiple methods. As motivation for this, imagine 2 functions - Databases.connect(), which is responsible for connecting to various databases (via different methods that implement this function) and another function Graphs.connect() which is responsible for connecting nodes in a graph, and may also have multiple implementing methods.

Prepanding method name with a module name (or alternatively importing function name explicitely) tells Julia to extend existing function instead of creating a new one in current module.

2 Likes

define Base.show(io::IO, x::MyType)

or, alternatively,

import Base: show

show(io::IO, x::MyType) = ...

However, I typically prefer Base.show.

1 Like