MethodError no method matching and no hints either

Usually when Julia gives me a hint as to what types I should use. But in this case, it isn’t giving me any useful hints.

Plot3D.jl

    ## Code dealing with Blocks 
    @with_kw struct Block
        IMAX::Int64
        JMAX::Int64
        KMAX::Int64
        X::Array{Float64,3}
        Y::Array{Float64,3}
        Z::Array{Float64,3}
    end

test.jl

## Cell 2 Read the Block data 
using .Plot3D: Block
using .Connectivity: find_matching_blocks
using JLD
blocks = jldopen("blocks.jld", "r") do file
    read(file, "blocks")
end
print("Block read, Finding matching faces")
block_match_indices, block_match_corners = find_matching_blocks(blocks[1],blocks[2])

somewhere in another folder
connectivity.jl

include("Plot3D.jl")
using .Plot3D: Block, Face, add_face_vertex
module Connectivity
function get_intersection(face1::Face, face2::Face, block1::Block, block2::Block)
        """Get the index of the intersection between two faces located on two different blocks
        """
      Some code
end
end

I also need to do include(“something.jl”) if i have functions defined in another file. It never lets me do relative path without the include.

Any ideas on how I can find out what inputs Julia thinks my code accepts? I am most definitely passing the blocks[1], blocks[2] which are structs of type Block, into a function that accepts Block type

Update:
I got the function call BUT!!! i had to do get ride of the ::Block ::Block in the function arguments. This is strange behavior. I would think it’s a bug.

Here’s it working but I can’t specify it to accept a struct for block 1. The struct is defined in Plot3D.jl

This function exists inside Connectivity.jl

Simple example pjuangph/JuliaLearning: Learning Julia and finding issues (github.com)

I think your error stems from the submodules.
I don’t quite understand how all of your code hangs together, but .Connectivity.Block will be different from .Plot3D.Block, even though Connectivity imports Block from Plot3D.
Are you includeing “Plot3D.jl” in multiple places? If so, you have multiple versions of that module, and those are distinct.

2 Likes

As a rule of thumb, if you are includeing the same file inside two or more other files, you are doing wrong. There are already many discussions about this in the forum, but I did not found one with a good enough explanation. But basically:

  1. Every time you include a file inside another file you are just putting that code in the global scope of that module. Any structs you define are just created again, and while they may have the same name, Julia will see them as different types.
  2. The basic solution is: if you have a file A.jl that that is needed by B.jl and C.jl either (i) include the three files inside the same file, with the A.jl before the other two; (ii) do the same thing as (i) but if each file has a module then you need to do using ..A inside modules B and C.
1 Like

While I think new users would benefit from a good and simple code loading example with include and using in some readily accessible source (like the Manual instead of discourse threads), I think it’s worth mentioning another factor: OP mentions that he came from a Python background in a github issue linked to the example. I had this exact same mixup for this reason, so hopefully this perspective helps.

Without getting into the more complicated package system, a .py file = a module = a global scope in Python. So if you needed a separate global scope, you wrote a separate file. In the main script file, import searches for these files and loads them as modules. It’s important to note that modules are tracked (in a dictionary sys.modules) to prevent reloading upon repeated imports.

In Julia, a module is a global scope, but it’s not tied to a .jl file at all. If you needed a separate global scope, you can write a module block in the same file. Now, I still haven’t exactly figured out how using/import works, but it does not search for files in directories the way Python does. It can search for packages (more of a hassle to make) or an existing module in the file. Like Python, using/import prevents reloading modules.

Coming from Python, I latched onto include because it loaded code from a file in a familiar way, but it wasn’t long until I found out repeated includes repeatedly evaluates, which makes separate independent pieces of code in different namespaces. It was only after crawling through multiple discourse thread that I learned to structure my modules in the main script instead of the file system and to treat include more of a way to copy-paste multiple files into one file, just as @Henrique_Becker described in 2.(ii) of his reply.

Your solution (i) is kind of messy. Do I have to use the include("something.jl") for me to use the using .something? I haven’t found a way around that.

If i just do import .something even though it’s in the same folder, julia tells me that it’s not defined. How can I make julia look in a particular folder for the module?

When I run cmd/terminal → julia → using .something That works just fine, but I have code files. I need the same functionality in those files.

Perhaps this is useful:

module MyModule

# This could be in a different file. 
# Then `include("Plot3D.jl)`
module Plot3D
	struct Block
		value :: Int
	end
	export Block
end

# This could be in a different file. 
# Then `include("Connectivity.jl)`
module Connectivity
  using ..Plot3D
  function find_matching_blocks(b :: Block)
	@show b
  end
  export find_matching_blocks
end

using .Plot3D, .Connectivity

find_matching_blocks(Block(1))

end
julia> include("test2.jl")
b = Main.MyModule.Plot3D.Block(1)
Main.MyModule

Each file is included only once. Including a file is the same as placing the code directly inside the file that contains the include.
The result is a bunch of submodules for MyModule.
In Connectivity, using ..Plot3D brings MyModule.Plot3D into scope.

One thing I have learned (which may not apply to your use case): Having lots of modules often just makes life more complicated. But when I really want a larger block of code in a module, I make it a package. Then I don’t have to include anything and just issue using Plot3D and let Pkg worry about finding the relevant code.

Well, it is not my solution that is messy. It is just the right solution if the code does not use submodules, what you may find messy. If the code uses submodules you should use (ii).

Well, if you want to call import/using over a module defined in a file.jl you have lying around, yes. You need to include the file and then import/using it. There may be an workaround that connects to your next question.

Well, the dirty solution is: push!("folder_you_want_julia_to_look_at", LOAD_PATH), then you can just import Module (without the dot in front of it). But this is a hack, and you should abandon it if you want other people using your code (i.e., making your code into a package).

The right way of doing things is like I explained before includeing once and importing wherever you need (using a relative module path using dots).

Another possibility is breaking the inner module to an inner package by creating InnerModule.jl/src/InnerModule.jl and then using import Pkg; Pkg.activate("."); Pkg.dev("./InnerModule.jl") (inside your main module, that has InnerModule.jl/ inside it) but this seems to me like a lot of work just to not make both include and import.