Scoping confusion: MethodError but method is defined

This kind of error keeps coming up, and I guess I need to figure out what is going on.

In the course of using a function from a module which calls mutation_wait I get a method error

ERROR: MethodError: no method matching mutation_wait(::Int64, ::ArrayModel{Vector{Float64}, SparseMatrixCSC{Float64, UInt64}})

Closest candidates are:
  mutation_wait(::Any, ::Main.PopulationSim.DirichletModel)
   @ Main.PopulationSim ~/Dropbox/VRC01-class/code/dirichlet_model.jl:110

but at the same time, when I do ? I can see the method right there but NOT the “mutation_wait” signiture in the error message

help?> mutation_wait
search: mutation_wait mutation_flip mutation_matrix sparse_mutation_matrix

  No documentation found.

  mutation_wait is a Function.

  # 2 methods for generic function "mutation_wait" from Main:
   [1] mutation_wait(g, model::ArrayModel)
       @ ~/Dropbox/VRC01-class/code/full_mutation_model.jl:237
   [2] mutation_wait(g, model::ProductModel)
       @ ~/Dropbox/VRC01-class/code/full_mutation_model.jl:313

I’m so confused :(. Can people speculate on what kind of MethodError or module usage is causing this? How do I prevent these kinds of errors? Thanks!

EDIT: So I saw Function name conflict: ADL / function merging? and I’m thinking this is the problem, I define a mutation_wait inside the module where my function lives, and another outside the module, and these now are just two different functions. So to extend mutation wait, I have to import the module before defining it outside the module? Or (maybe better) just never actually define it inside the module? Or, to refine the question, if I have multiple model types in perhaps, multiple modules, each with their own mutation_wait, how do I assure that they all get seen in the same method table?

If you define a function of same name in Main scope, yes you either have to import the function you want to extend or change the place where you call the function to MyModule.mutation_wait to specify the right function to call (of the two with same name).

For several you could write a MyModuleBase.jl package that defines a function mutation_wait end dummy function. Each of your multiple modules would depend on this base package, import the mutation wait from there and hence all extend the same function again.

3 Likes

Edit: Right, I think I found the relevant docs passage.

The statement using Lib means that a module called Lib will be available for resolving names as needed. When a global variable is encountered that has no definition in the current module, the system will search for it among variables exported by Lib and import it if it is found there.

So there are a couple implications: first if I try to export something that is already defined, nothing happens, and there is not even an error. (This was confusing me as well.) And, (of course) if a module has defined something, you have to explicitly import it to extend it so you don’t go around breaking local things.

I was just thinking export acted like another function definition which is not the case at all. it’s more like a fallback namespace!

Thanks for the tip! This is a nice design pattern.

1 Like

If you export something that was defined before, you should get a warning, I think. You definetly do if two modules export a function of same name (without them both importing the same function from some common base module).

export does export the function, but just having the same name is not enough for two functions to be “fused” into the same (what if both functions of same name define a case with same parameters? Besides that being probably type piracy, it might still happen).

1 Like

You are right! I did get a warning, which was ignored.

For other projects I was just passing around functors, which seemed to be a lot easier.

I think the Modules section in the docs has improved alot since I last read it and it does explain this well (or maybe I just didn’t consider a method error to be related to modules?). Thanks for taking the time to answer me anyway.

1 Like