Пакеты, модули

В версии Julia v0.5 система пакетов выглядит как прототип, далекий от окончательного вида, но дающий возможность быстро начать работать. В разработке находится следующая версия менеджера пакетов (рабочее название Pkg3), которая придет на смену в будущем. Воспринимайте текущую реализацию как нечто временное.

Установка пакетов

Пакет - это набор файлов содержащих код, тесты и мета-информацию о модуле или модулях, если их несколько. Модуль же - это отдельное пространство имен (в терминах языка).

Установить пакет можно так:

Pkg.add("Имя пакета")

Примечание.
Имя пакета должно быть зарегистрировано в https://github.com/JuliaLang/METADATA.jl, чтобы менеджер пакетов с настройками по умолчанию, автоматически нашел и установил пакет.

Незарегистрированные пакеты можно установить так:

Pkg.clone(url)

В своих программах вы можете автоматизировать проверку и установку какого-либо пакета таким способом:

# Если пакет Lazy не установлен - установить его:
isdir( Pkg.dir("Lazy")) || Pkg.add("Lazy")

Удалить пакет можно командойPkg.rm():

# удаление пакета Lazy:
Pkg.rm("Lazy")

include

include выполняет указанный файл, как часть текущего модуля. Используется, чтобы разбить длинный файл на несколько или чтобы иметь доступ к одному куску кода из нескольких файлов.

Нужно иметь ввиду, что когда include выполняет код из указанного файла - это не является равносильным вставке кода в место вызова include: вносимые им изменения видны в текущей динамической глобальной области видимости, т.е. в области видимости модуля, который был текущим в момент выполнения инструкции include, не зависимо от текущей лексической области видимости из которой, возможно, вызвана include. Пример:

shell> echo "a = 2" > a.jl # теперь файл a.jl содержит код:  a = 2

julia> module AA
       function aa()
        include("a.jl")
       end
       end
AA

julia> module BB
       import AA
       function bb()
        AA.aa()
       end
       bb() # вызов
       end
BB

julia> BB.a
2

Как видно из примера, несмотря на то, что include была вызвана в лексической области видимости внутри функции f модуля AA из лексической области функции bb (модуля BB), областью видимости переменной a стала глобальная область - область модуля BB. Он был текущей динамической глобальной областью в момент выполнения include.

Инструкция include выполняется столько раз, сколько раз через нее пройдет поток управления (в отличие от import и use). Таким образом, если кусок кода будет повторяться , то во второй и последующие разы вы получите предупреждение о переопределении того, что определяется в подключаемом файле. Значит, вы должны самостоятельно позаботиться о том, когда и сколько раз вы подключите файл.

Вследствие своей динамичной природы include позволяет подключать файл, имя которого становится известно только во время выполнения программы. Это можно использовать как один из способов внедрения зависимости:

julia> code = """
       " тестовый модуль "
       module AAA

       "функция сложения"
       f(x::Int, y::Int) = x+y

       end # of module
       """;

shell> echo "$code" > file1.jl

julia> where_functions = "file1.jl"
"file1.jl"

julia> dinamic_module = where_functions |> include
AAA

julia> dinamic_module |> typeof
Module

julia> dinamic_module.f( 3, 4)
7

# Как побочный эффект - модуль AAA становится доступен и по имени:

julia> AAA.f(3,4)
7

using и import:

Две похожие по своему действию инструкции. Проще запомнить их различие, чем схожие черты: кроме своего основного назначения, import позволяет функцию, определенную в другом модуле, расширить по ее короткому имени. Говоря "расширить", я имею ввиду определить в текущем модуле еще один метод для уже определенной функции (определенной, как правило, не в текущем модуле).

Если, в чужом коде вам встретилась инструкция import модуль.имя_функции, то можно ожидать, что эта функция будет расширена ниже. (Но не обязательно.) Видимо, это сделано, чтобы уменьшить вероятность случайного переопределения существующих имен.

using же используется, когда вы просто хотите использовать (от "use") модуль, не меняя его определений.

Если Module1 экспортирует fun1(x) но не экспортирует fun2(x),

module BB
export aa; aa(x)=x*2
bb(x)=x/2
end

то:

действие после этого можно... нельзя...
import BB BB.aa(x), BB.bb(x) aa(x), bb(x), aa(x,y)=x+y
import BB.aa aa(x); aa(x,y)=x+y bb(x); bb(x,y)=x-y
import BB: aa, bb aa(x); aa(x,y)=x+y; bb(x); bb(x,y)=x-y
using BB aa(x); BB.aa(x,y)=x+y; BB.bb(x); BB.bb(x,y)=x-y aa(x,y)=x+y; bb(x,y)=x-y
importall BB aa(x); aa(x,y)=x+y; BB.bb(x); BB.bb(x,y)=x-y bb(x); bb(x,y)=x-y

Написанный самостоятельно файл модуля должен выполнять перечисленные ниже условия, чтобы using или import могли найти его:

  • имя файла модуля должно заканчиваться на .jl

  • julia ищет модули в директориях, перечисленных в переменной-массиве LOAD_PATH

  • julia ищет файлы в этих каталогах в виде ИмяМодуля/src/file.jl

LOAD_PATH - массив строк - путей поиска модулей

Добавить свой путь можно так:

push!(LOAD_PATH, "/Path/To/My/Module/")

... или определить переменную окружения JULIA_LOAD_PATH до запуска julia.

results matching ""

    No results matching ""