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.
## Code dealing with Blocks
@with_kw struct Block
## Cell 2 Read the Block data
using .Plot3D: Block
using .Connectivity: find_matching_blocks
blocks = jldopen("blocks.jld", "r") do file
print("Block read, Finding matching faces")
block_match_indices, block_match_corners = find_matching_blocks(blocks,blocks)
somewhere in another folder
using .Plot3D: Block, Face, add_face_vertex
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
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, blocks which are structs of type Block, into a function that accepts Block type
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
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
includeing “Plot3D.jl” in multiple places? If so, you have multiple versions of that module, and those are distinct.
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:
- 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.
- The basic solution is: if you have a file
A.jl that that is needed by
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
While I think new users would benefit from a good and simple code loading example with
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
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:
# This could be in a different file.
# Then `include("Plot3D.jl)`
value :: Int
# This could be in a different file.
# Then `include("Connectivity.jl)`
function find_matching_blocks(b :: Block)
using .Plot3D, .Connectivity
b = Main.MyModule.Plot3D.Block(1)
Each file is included only once. Including a file is the same as placing the code directly inside the file that contains the
The result is a bunch of submodules for
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
using over a module defined in a
file.jl you have lying around, yes. You need to include the file and then
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