Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function signature not found despite showing with methods(...)

Tags:

julia

I am new to Julia, so this might be trivial.

I have a function definition within a module that looks like (using URIParser):

function add!(graph::Graph,
              subject::URI,
              predicate::URI,
              object::URI)
    ...
end

Outside of the module, I call:

add!(g, URIParser.URI("http://test.org/1"), URIParser.URI("http://test.org/2"), URIParser.URI("http://test.org/1"))

Which gives me this error:

ERROR: no method add!(Graph,URI,URI,URI)
 in include at boot.jl:238
 in include_from_node1 at loading.jl:114
at /Users/jbaran/src/RDF/src/RDF.jl:79

Weird. Because when I can see a matching signature:

julia> methods(RDF.add!)
# 4 methods for generic function "add!":
add!(graph::Graph,subject::URI,predicate::URI,object::Number) at /Users/jbaran/src/RDF/src/RDF.jl:29
add!(graph::Graph,subject::URI,predicate::URI,object::String) at /Users/jbaran/src/RDF/src/RDF.jl:36
add!(graph::Graph,subject::URI,predicate::URI,object::URI) at /Users/jbaran/src/RDF/src/RDF.jl:43
add!(graph::Graph,statement::Statement) at /Users/jbaran/src/RDF/src/RDF.jl:68

At first I thought it was my use of object::Union(...), but even when I define three functions with Number, String, and URI, I get this error.

Is there something obvious that I am missing? I am using Julia 0.2.1 x86_64-apple-darwin12.5.0, by the way.

Thanks,

Kim

like image 278
Joachim Avatar asked Jul 25 '14 05:07

Joachim


1 Answers

This looks like you may be getting bit by the very slight difference between method extension and function shadowing.

Here's the short of it. When you write function add!(::Graph, ...); …; end;, Julia looks at just your local scope and sees if add! is defined. If it is, then it will extend that function with this new method signature. But if it's not already defined locally, then Julia creates a new local variable add! for that function.

As JMW's comment suggests, I bet that you have two independent add! functions. Base.add! and RDF.add!. In your RDF module, you're shadowing the definition of Base.add!. This is similar to how you can name a local variable pi = 3 without affecting the real Base.pi in other scopes. But in this case, you want to merge your methods with the Base.add! function and let multiple dispatch take care of the resolution.

There are two ways to get the method extension behavior:

  1. Within your module RDF scope, say import Base: add!. This explicitly brings Base.add! into your local scope as add!, allowing method extension.

  2. Explicitly define your methods as function Base.add!(graph::Graph, …). I like this form as it more explicitly documents your intentions to extend the Base function at the definition site.

This could definitely be better documented. There's a short reference to this in the Modules section, and there's currently a pull request that should be merged soon that will help.

like image 191
mbauman Avatar answered Nov 10 '22 01:11

mbauman