2016-05-13 3 views
3

У меня есть модуль я писал здесь:Как импортировать пользовательский модуль в Джулии

# Hello.jl 
module Hello 
    function foo 
     return 1 
    end 
end 

и

# Main.jl 
using Hello 
foo() 

Когда я бегу Main модуль:

$ julia ./Main.jl 

Я получаю это ошибка:

ERROR: LoadError: ArgumentError: Hello not found in path 
in require at ./loading.jl:249 
in include at ./boot.jl:261 
in include_from_node1 at ./loading.jl:320 
in process_options at ./client.jl:280 
in _start at ./client.jl:378 
while loading /Main.jl, in expression starting on line 1 

ответ

6

Вы должны include("./Hello.jl") перед тем using Hello

+3

Что означает знак «использование»? Я думал, что это kw будет включать в себя модуль для меня ... – dopatraman

+0

@dopatraman 'using' - это ввести имена модуля в текущую область, в то время как сам модуль не будет' include() 'automaticlly (за исключением тех, «LOAD_PATH») –

+0

Если у вас есть определения внутри 'module', вам также необходимо экспортировать их. – m33lky

0

Если вы хотите получить доступ к функции Foo при импорте модуля с «помощью» вам нужно добавить «экспорт Foo» в заголовке модуля.

0

Если вы явно загружаете файл (include("./Hello.jl")) Julia ищет файлы модулей в каталогах, определенных в переменной LOAD_PATH.

См. this page.

6

Были короткие ответы, но я хотел бы предоставить более полный ответ, если это возможно.

Когда вы запустите using MyModule, Julia ищет его только в списке каталогов, известных как ваш LOAD_PATH. Если вы наберете LOAD_PATH в Джулией РЕПЛ, вы получите что-то вроде следующего:

2-element Array{ByteString,1}: 
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/local/share/julia/site/v0.4" 
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/share/julia/site/v0.4" 

Эти каталоги, которые Джулия будет искать модули включить при вводе using Hello. В примере, который вы указали, поскольку Hello не было в вашем LOAD_PATH, Джулия не смогла его найти.

Если вы хотите включить локальный модуль, вы можете указать его местоположение относительно текущего рабочего каталога.

julia> include("./src/Hello.jl") 

После того, как файл был включен, вы можете запустить using Hello как обычно, чтобы получить все то же самое поведение. Для одного сценария это, вероятно, лучшее решение. Однако, если вы обнаружите, что у вас есть include() определенный набор каталогов, вы можете надолго добавить их в свой LOAD_PATH.

Добавления каталогов в LOAD_PATH

Ручного добавления каталогов в ваш LOAD_PATH может быть болью, если вы хотите регулярно использовать отдельные модули, которые хранятся за пределами Юли LOAD_PATH. В этом случае вы можете добавить дополнительные каталоги в переменную среды LOAD_PATH. Затем Джулия будет автоматически искать эти каталоги всякий раз, когда вы выдаете команду import или using.

Один из способов сделать это - добавить в свой .basrc, .profile, .zshrc.

export JULIA_LOAD_PATH="/path/to/module/storage/folder" 

Это добавит этот каталог в стандартные каталоги, которые Джулия будет искать. Если затем запустить

julia> LOAD_PATH 

Она должна возвращать

3-element Array{ByteString,1}: 
"/path/to/module/storage/folder" 
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/local/share/julia/site/v0.4" 
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/share/julia/site/v0.4" 

Теперь вы можете свободно работать using Hello и Джулия автоматически найдет модуль (до тех пор, как она хранится под /path/to/module/storage/folder.

Для более информацию, взгляните на страницу this из документации Julia.

2

Хотя ответ 张 实 is является самым удобным ent, , вы не должны использовать include вне REPL. Если вы пишете файл программы, воспользуйтесь возможностью добавить соответствующий каталог в LOAD_PATH. Реми дает очень хорошее объяснение, как это сделать, но стоит также объяснить, почему вы должны это делать в первую очередь. (Кроме того, из документации: push!(LOAD_PATH, "/Path/To/My/Module/") но обратите внимание, модуль и файл должен иметь такое же имя)

Проблема заключается в том, что все, что вы include будет определяться именно там, где вы звоните include, даже если она определена в другом месте. Поскольку целью модулей является повторное использование, вы, вероятно, в конечном итоге используете MyModule в нескольких файлах. Если вы вызываете include в каждом файле, каждый из них будет иметь свое собственное определение MyModule, и хотя они идентичны, это будут разные определения. Это означает, что любые данные, определенные в MyModule (например, типы данных), не будут одинаковыми.

Чтобы понять, почему это огромная проблема, рассмотрим эти три файла:

types.jl

module TypeModule 
struct A end 
export A 
end 

a_function.jl

include("types.jl") 
module AFunctionModule 
using TypeModule 
function takes_a(a::A) 
    println("Took A!") 
end 
export takes_a 
end 

function_caller.jl

include("a_function.jl") 
include("types.jl") 
using TypeModule, AFunctionModule 
my_a = A() 
takes_a(my_a) 

Если вы ru n julia function_caller.jl вы получите MethodError: no method matching takes_a(::TypeModule.A). Это связано с тем, что тип A, используемый в функции function_caller.jl, отличается от типа, используемого в a_function.jl. В этом простом случае вы можете «исправить» проблему, изменив порядок включений в функции function_caller.jl (или просто удалив include("types.jl") целиком из функции function_caller.jl! Это нехорошо!). Но что, если вам нужен другой файл b_function.jl, который также использовал тип, определенный в TypeModule? Вы должны сделать что-то очень взломанное. Или вы можете просто изменить свой LOAD_PATH, чтобы модуль определялся только один раз.