Подключение файлов
Для небольших фрагментов кода и коротких тестов производительности вполне подходит программа в одном файле. Большие программы проще поддерживать и понимать, если разделить их на несколько файлов.
Чтобы компилятор обрабатывал другие файлы, используйте require "...". Эта директива принимает один аргумент — строковый литерал — и может применяться в разных формах.
После подключения файла компилятор запоминает его абсолютный путь, и последующие вызовы require для этого же файла игнорируются.
require "filename"
Эта директива ищет "filename" в пути поиска файлов.
По умолчанию путь поиска включает расположение стандартной библиотеки, поставляемой с компилятором, и каталог "lib" относительно текущего рабочего каталога (который в оболочке Unix задаётся с помощью pwd). Поиск выполняется только в этих местах.
Поиск выполняется следующим образом:
- Если в пути поиска найден файл с именем "filename.cr", он подключается.
- Если найден каталог с именем "filename", непосредственно внутри которого находится файл "filename.cr", этот файл подключается.
- Если найден каталог с именем "filename", в котором есть каталог "src", а непосредственно внутри него находится файл "filename.cr", этот файл подключается.
- В противном случае возникает ошибка компиляции.
Из второго правила следует, что помимо такой структуры:
- project
- src
- file
- sub1.cr
- sub2.cr
- file.cr (requires "./file/*")
можно использовать и такую:
- project
- src
- file
- file.cr (requires "./*")
- sub1.cr
- sub2.cr
В зависимости от ваших предпочтений такая структура может выглядеть немного аккуратнее.
Третье правило очень удобно благодаря типичной структуре каталогов проекта:
- project
- lib
- foo
- src
- foo.cr
- bar
- src
- bar.cr
- src
- project.cr
- spec
- project_spec.cr
То есть внутри "lib/{project}" находятся каталоги проектов (src, spec, README.md и так далее)
Например, если поместить require "foo" в project.cr и выполнить crystal src/project.cr в корневом каталоге проекта, компилятор найдёт foo в lib/foo/foo.cr.
Четвёртое правило — это применение второго правила к третьему.
Если запустить компилятор из другого места, например из каталога src, lib не будет в пути поиска, и разрешить require "foo" не удастся.
require "./filename"
Эта директива ищет "filename" относительно файла, содержащего выражение require.
Поиск выполняется следующим образом:
- Если относительно текущего файла найден файл с именем "filename.cr", он подключается.
- Если найден каталог с именем "filename", непосредственно внутри которого находится файл "filename.cr", этот файл подключается.
- В противном случае возникает ошибка компиляции.
Эта форма с относительным путём в основном используется в проекте для обращения к другим файлам внутри него. Её также используют для обращения к коду из спецификаций:
require "../src/project"
Другие формы
В обоих случаях можно использовать вложенные имена: поиск будет выполняться во вложенных каталогах:
-
require "foo/bar/baz"выполнит поиск "foo/bar/baz.cr", "foo/bar/baz/baz.cr", "foo/src/bar/baz.cr" или "foo/src/bar/baz/baz.cr" в пути поиска. -
require "./foo/bar/baz"выполнит поиск "foo/bar/baz.cr" или "foo/bar/baz/baz.cr" относительно текущего файла.
Кроме того, можно использовать "../" для обращения к родительским каталогам относительно текущего файла, поэтому работает и require "../../foo/bar".
Во всех этих случаях можно использовать специальные суффиксы * и **:
-
require "foo/*"подключит все файлы ".cr" в каталоге "foo", но не в его вложенных каталогах. -
require "foo/**"рекурсивно подключит все файлы ".cr" в каталоге "foo" и во всех его вложенных каталогах.
To the extent possible under law, the persons who contributed to this workhave waived
all copyright and related or neighboring rights to this workby associating CC0 with it.
https://crystal-lang.org/reference/1.2/syntax_and_semantics/requiring_files.html