.jl - файлы: сценарии применения и особенности

Автор
avatar-igarajaigaraja
Notebook

.jl файлы: сценарии применения и особенности

Обзор посвящён .jl файлам. А именно, таким применениям как:

  • создание пользовательских модулей
  • использование определённых сценариев
  • отладки кода
  • запуск серверных приложений

Создание пользовательских модулей

В отличие от файлов .ngscript, файлы с расширением .jl можно использовать для создания собственных модулей.

Рассмотрим 2 файла.

  1. MyModule.jl
  2. _MyScriptModule.ngscript

Оба файла включают в себя модули с одинаковым содержимым: MyModule и MyScriptModule соответственно. Но для случая .jl-файла мы можем подключить модуль, используя:

In [ ]:
include("MyModule.jl")
using .MyModule

area(Rectangle(2,3))

Но, используя .ngscript, уже не получится подключить модуль:

In [ ]:
try
    include("_MyScriptModule.ngscript")
    using .MyScriptModule

    area(Rectangle(2,3))
catch e 
    println(e)
end
LoadError("/user/start/examples/project_management/jl_files_usage/_MyScriptModule.ngscript", 1, ErrorException("syntax: { } vector syntax is discontinued around /user/start/examples/project_management/jl_files_usage/_MyScriptModule.ngscript:1"))

Автоматизация выполнения действий

Представим, что имеется таблица студентов и их репозиториев с домашними заданиями.

Фамилия И. О. Git-репозиторий
Иванов И. И. git@github.com:Ivanov/Julia_course.git
Павлов П. П.
Петров П. П. git@github.com:Petrov/Julia_course.git
Сидоров И. П. git@github.com:Sidorov/Julia_course.git

Преподаватель ведёт некоторый предмет сразу в нескольких группах.


Тогда, используя .jl-файлы можно выполнять проверку домашних заданий, копируя все файлы автоматически в ту директорию, где располагается соответствующий .jl-файл.


Обратите внимание, что сейчас в директории нет никаких папок.

Воссоздадим такую ситуацию, выполнив ячейку ниже. После выполнения кода ячейки в вашей директории появятся папки:

jl-files
├── Иванов
│   └── Семинар_1
├── Петров
│   └── Семинар_1
└── Сидоров
    └── Семинар_1

Описание к тому, что выполняется, будет дано в следующей ячейке.

In [ ]:
run(`bash -c """

julia generate_student_folders.jl students_group_1.csv Семинар_1

"""`)
ARGS = ["students_group_1.csv", "Семинар_1"]
df = 4×4 DataFrame
 Row │ Фамилия   И.       О.       GitHub
     │ String15  String3  String3  String?
─────┼───────────────────────────────────────────────────────────────
   1 │ Иванов    И.       И.       git@github.com:Ivanov/Julia_cour…
   2 │ Павлов    П.       П.       missing
   3 │ Петров    П.       П.       git@github.com:Petrov/Julia_cour…
   4 │ Сидоров   И.       П.       git@github.com:Sidorov/Julia_cou…
Out[0]:
Process(`bash -c '

julia generate_student_folders.jl students_group_1.csv Семинар_1

'`, ProcessExited(0))
  • Функция run может запускать команды.
  • bash -c означает "выполнить команду в оболочке bash".
  • julia - juila программа.jl аргумент_1 аргумент_2 ...
  • generate_student_folders.jl - файл, создающий папки и клонирующий в них репозитории студентов
    • ARGS[1] - имя файла, содержащего данные (students_group_1.csv)
    • ARGS[2] - название занятия/работы, которую нужно проверить(Семинар_1)
Почему не заменить скрипт generate_student_folders.jl аналогичной функцией?

Удобство использования скрипта состоит в том, что внутри него, в отличие от функции, можно использовать using и import.

То есть мы можем вызвать отдельный процесс $\rightarrow$ подключить в нём пакеты $\rightarrow$ выполнить действия $\rightarrow$ и вернуться обратно в нашу основную программу.

Заметим, что мы воспользовались пакетом CSV внутри программы generate_student_folders.jl, но этот пакет не подключён в нашем скрипте

In [ ]:
try
    df = CSV.read("students_group_1.csv", DataFrame);
catch e 
    sprint(showerror,e)
end
Out[0]:
"UndefVarError: `CSV` not defined"

Отладка кода

Несмотря на то, что отладка кода также возможна и в скриптах, .jl файлы имеют преимущество перед ними. И вот почему:

.ngscript представляет собой json-файл.

Например, файл _sqrt_16.ngscript представляет собой json-файл, внутри которого содержится

# часть файла про первую текстовую ячейку

      "id": "ffe36da1",
      "cell_type": "markdown",
      "source": [
        "Значение $\\sqrt{16}$"
      ],
# часть кода про первую кодовую ячейку

      "id": "a4b6a26f",
      "cell_type": "code",
      "source": [
        "sqrt(16)"
      ],

То есть на самом деле, отлаживать такой файл - нетривиальная задача. Давайте в этом убедимся

Отлаживание .ngscript файлов

Создадим функцию circle_area в текущем .ngscript-файле.

In [ ]:
"Площадь круга по радиусу"
function circle_area(r)
  π*r^2
end
Out[0]:
circle_area

Используя @functionloc можно узнать имя файла и строку метода, который будет вызываться.

In [ ]:
@functionloc circle_area(2)
Out[0]:
(nothing, 2)

Как видим, название файла не вернулось, а в качестве строки указывается 2 строка ячейки (после описания нашей функции "Площадь круго по радиусу").

Отлаживание .jl-файлов

Однако для .jl-файлов такой проблемы нет. И положение объявленной в файле MyModule.jl функции area выводится совершенно определённо:

In [ ]:
@functionloc area(Rectangle(2,3))
Out[0]:
("/user/jl-files/MyModule.jl", 17)

otladka.png

.jl-файлы как часть приложений

Для разработки приложений, используя, например, Genie, необходимо внутри директории приложения создавать именно .jl файлы, а не скрипты.

Так, основным файлом работы приложения должен быть файл с названием app.jl.