Метод можно определить так, чтобы он принимал произвольное количество аргументов, используя параметры splat
. Это делается путем добавления символа *
перед именем параметра: теперь при вызове метода он будет ссылаться на кортеж с нулевым или более значениями аргументов. Посмотрите это, например:
def get_pop(population, *countries)
puts "Requested countries: #{countries}"
countries.map { |country| population[country] }
end
puts get_pop(population, "Indonesia", "China", "United States")
Этот код даст следующий результат:
Requested countries: {"Indonesia", "China", "United States"}
{273523615, 1439323776, 331002651}
Использование splat всегда будет создавать кортежи правильных типов, как если бы метод имел такое количество обычных позиционных параметров. В этом примере typeof(countries)
будет Tuple(String, String, String)
; тип будет меняться при каждом использовании. Параметры Splat
— наиболее распространенный вариант использования кортежей.
Организация вашего кода в файлах
Написание кода в одном файле подходит для некоторых быстрых тестов или очень небольших приложений, но все остальное в конечном итоге придется организовывать в нескольких файлах. Всегда существует основной файл, который вы передаете команде crystal run
или crystal build
, но этот файл может ссылаться на код в других файлах с ключевым словом require
. Компиляция всегда начинается с анализа этого основного файла, а затем рекурсивного анализа любого файла, на который он ссылается, и так далее.
Разберем пример:
1. Сначала создайте файл с именем
def factorial(n)
(1..n).product
end
2. Затем создайте файл с именем program.cr:
require "./factorial"
(1..10).each do |i|
puts "#{i}! = #{factorial(i)}"
end
В этом примере require «./factorial» будет искать файл с именем factorial.cr в той же папке, что и program.cr, и импортируйте все, что он определяет. Невозможно выбрать только часть того, что определяют необходимые файлы; требуют импорта всего последовательно. Запустите этот пример с помощью crystal run program.cr
.
Один и тот же файл не может быть импортирован дважды; компилятор Crystal проверит и проигнорирует такие попытки.
Вам могут потребоваться файлы двух типов: это либо файл из вашего проекта — в этом случае для ссылки на него используется относительный путь, начинающийся с расширения . -
или это файл библиотеки, взятый из стандартной библиотеки или из установленной вами зависимости. В этом случае имя используется напрямую, без относительного пути.
require "./filename"
Начальный параметр ./
сообщает Crystal искать этот файл в текущем каталоге относительно текущего файла. Он будет искать файл с именем filename.cr или каталог с именем ../
для ссылки на родительский каталог.
Также поддерживаются шаблоны Glob для импорта всех файлов из заданного каталога, как здесь:
require "./commands/*"
Это импортирует все файлы Crystal в каталог команд. Импорт всего из текущего каталога также допустим:
require
Эта нотация используется в первую очередь для ссылки на файлы из вашего собственного проекта. При ссылке на файлы из установленной библиотеки или стандартной библиотеки Crystal путь не начинается с расширения ..
require "filename"
Если путь не начинается ни с ./
, ни с ../
, это должна быть библиотека. В этом случае компилятор будет искать файл в стандартной библиотеке и в папке
require "http/server" # Imports the HTTP server from stdlib.
Server = HTTP::Server.new do |context|
context.response.content_type = "text/plain"
context.response.print "Hello world, got
#{context.request.path}!"
end
puts "Listening on http://127.0.0.1:8080" server.listen(8080)
Для чего-либо большего, чем пара сотен строк, предпочтительнее разделить код и организовать его в файлах, каждый из которых имеет определенную цель или область применения. Таким образом, легче найти ту или иную часть приложения.
Резюме