Произошла ошибка при загрузке пользовательского модуля Julia

#module #julia

#модуль #julia

Вопрос:

Я был озадачен тем, как определить и использовать пользовательский module интерфейс в Julia.

Например, я определил module named myMoldule для переноса изменяемой структуры Param и функции add в D:\run\defineModule.jl :

 module myMoldule

    export Param, add

    mutable struct Param
        x ::Int64
        y ::Int64
    end

    function add(x::Int64, y::Int64)
        sum ::Int64
        sum = x   y
        return sum
    end
end
  

и использовал этот модуль в D:\run\useModule.jl подобном:

 include("D:\run\defineModule.jl")
using .myMoldule

function testModule()
    param = Param(1, 2)
    sum   = add(param.x, param.y)
    println(sum)
end
  

Произошла ошибка при выполнении testModule() следующего:

 julia> testModule()
ERROR: UndefVarError: Param not defined
Stacktrace:
 [1] testModule() at D:runuseModule.jl:8
 [2] top-level scope at none:1
  

Обратите внимание, что я использовал абсолютный путь в include(...) , чтобы избежать использования LOAD_PATH материала, и добавил . перед именем модуля (т. Е. using .myMoldule ).

В чем, по-видимому, проблема?

PS: информация о версии Julia:

 julia> versioninfo()
Julia Version 1.5.2
Commit 539f3ce943 (2020-09-23 23:17 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-9.0.1 (ORCJIT, skylake)
Environment:
  JULIA_DEPOT_PATH = C:Usersf.julia;C:optJuliaPro-1.5.2-1Julia-1.5.2localsharejulia;C:optJuliaPro-1.5.2-1Julia-1.5.2sharejulia
  JULIA_LOAD_PATH = @;@v#.#;@stdlib
  JULIA_NUM_THREADS = 6
  JULIA_PKG_SERVER = pkg.juliahub.com
  

Ответ №1:

Необходимо внести исправления:

  • sum является ли функция, в Base которой вы должны использовать другое имя
  • нет необходимости объявлять sum переменную (и она должна быть названа примерно так mysum )
  • Удалите пробел перед ::
  • Имена модулей должны начинаться с заглавной буквы
  • У вас опечатка в имени модуля возможно, вы загружаете другой модуль, чем вы думаете?

После исправления ваш код работает.

Комментарии:

1. Я исправил все проблемы, на которые указал Пшемыслав Шуфель. Я обнаружил, что к ошибке приводит не то, как я назвал sum или модуль UndefVarError: Param not defined .

2. Небольшое уточнение для читателей: пробелы разрешены :: и могут быть полезны для удобства чтения при определении structs . 🙂

Ответ №2:

Проблема возникает из-за того, что вы используете .MyModule1 , а не в MyModule2 , и, следовательно, вы импортируете Param в основной модуль, но не в MyModule2 , поэтому Module2 не видит Param .

Если вы поставите using ..MyModule1 (две точки вместо одной, так как у вас есть еще один уровень), MyModule2 эта проблема исчезнет.

Однако ваш код все равно не будет работать, поскольку include функция julia просто запускает все содержимое включенного файла, таким образом, даже если вы включили один и тот же файл, вы создадите разные экземпляры модулей. Это предупреждение WARNING: replacing module... указывает на то, что где-то в вашем коде вы можете использовать другую версию модуля (в вашем случае Main.Module1 и Main.Module2.Module1).

Обычной практикой в Julia является включение всех файлов в одном месте (они должны быть включены только один раз). Например, вы можете поместить все включения в файл useModule.jl :

 include("./defineModule1.jl")
include("./defineModule2.jl")
using .MyModule1
using .MyModule2

function testModule()

    param = Param(1, 2)

    # call myAdd to get the sum of param.x and param.y
    sumValue = myAdd(param)
    println(sumValue)

    # call mySubtract to get the difference of param.x and param.y
    difValue = mySubtract(param)
    println(difValue)
    
end

  

Не включайте файлы в другие места. например
defineModule2.jl , содержимое:

 
module MyModule2

    using ..MyModule1

    export myAdd, mySubtract

    function myAdd(param::Param)
        return param.x   param.y
    end

    function mySubtract(param::Param)
        return param.x - param.y
    end

end # end of module
  

Ответ №3:

Примечание участника: следующий новый вопрос, который был отклонен (возможно), был расширен до исходного, и на него хорошо ответил Виталий Яковчук.


Я исправил все проблемы, на которые указал Пшемыслав Шуфель. В моем случае выше проблема не в неправильных способах именования.

Теперь у меня есть лучший пример, чтобы прояснить мою проблему.

Предположим, что для удовлетворения потребностей мне нужно разделить исходный код Julia на два модуля, например, определить изменяемую структуру Param в defineModule1.jl и определить функции в defineModule2.jl . Сценарии кода следующие:

  1. "D:\run\defineModule1.jl" :
 module MyModule1

    export Param

    mutable struct Param
        x::Int64
        y::Int64
    end

end # end of module
  
  1. "D:\run\defineModule2.jl" :
 include("D:\run\defineModule1.jl"); using .MyModule1

module MyModule2

    export myAdd, mySubtract

    function myAdd(param::Param)
        return param.x   param.y
    end

    function mySubtract(param::Param)
        return param.x - param.y
    end

end # end of module
  

Обратите внимание, что Param это здесь не определено, и для обеспечения Param доступности include("D:\run\defineModule1.jl"); using .MyModule1 в качестве первой строки этого файла добавляется строка.

  1. "D:\run\useModule.jl" :
 include("D:\run\defineModule1.jl"); using .MyModule1
include("D:\run\defineModule2.jl"); using .MyModule2

function testModule()

    param = Param(1, 2)

    # call myAdd to get the sum of param.x and param.y
    sumValue = myAdd(param)
    println(sumValue)

    # call mySubtract to get the difference of param.x and param.y
    difValue = mySubtract(param)
    println(difValue)
    
end
  

Обратите внимание, что как в функции myAdd(param) , так и mySubtract(param) в скрипте defineModule2.jl требуется предопределенная изменяемая структура Param defineModule1.jl .

Это то, что я получил при запуске D:\run\useModule.jl :

 julia> include("D:\run\useModule.jl")
WARNING: replacing module MyModule1.
WARNING: replacing module MyModule1.
WARNING: replacing module MyModule2.
ERROR: LoadError: LoadError: UndefVarError: Param not defined
Stacktrace:
 [1] top-level scope at D:rundefineModule2.jl:7
 [2] include(::String) at .client.jl:457
 [3] top-level scope at D:runuseModule.jl:2
 [4] include(::String) at .client.jl:457
 [5] top-level scope at none:1
in expression starting at D:rundefineModule2.jl:7
in expression starting at D:runuseModule.jl:2
  

Я полагал, что, используя следующие строки в начале «D:runuseModule.jl «, изменяемая структура Param должна была быть найдена:

 include("D:\run\defineModule1.jl"); using .MyModule1
include("D:\run\defineModule2.jl"); using .MyModule2
...
  

Тем не менее, LoadError: UndefVarError: Param not defined сообщается об ошибке.

Итак, почему не может Param быть найдено D:\run\useModule.jl ?