Elixir и IEx. С чего начать?
Если вы только приступили к знакомству с Elixir, то эта статья поможет решить несколько основных проблем, с которыми сталкиваются все новички, и как можно скорее переключиться на изучение более интересных особенностей языка.
1. Как выйти из меню shell-break: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
«У меня есть 10 лишних минут, почему бы не покопаться в Erlang/Elixir?». Трудно сосчитать, сколько раз я уже говорил себе эту фразу, застревал на определённом этапе разработки и переключался на другие более насущные задачи. Раз пятнадцать точно. А может, и больше.
Предположим, в процессе написания кода разработчик обнаружил, что совершил ошибку. Для отмены он нажмёт Ctrl+C
, после чего на экране появится следующее меню, которое в Erlang называется shell-break:
iex(2)> x = fn (a, b) ->
...(2)> c + b
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
(v)ersion (k)ill (D)b-tables (d)istribution
Понадобятся здесь только две опции: (c)
и (a)
. (c)ontinue
вернёт обычный режим ввода, но для того, чтобы вернуться, придётся нажать клавишу Enter дважды, что совершенно неочевидно. Опция (a)
осуществит выход из интерактивной оболочки.
Такое поведение прописано в алгоритме виртуальной машины BEAM, исполняющей программы на Elixir и Erlang. Остальные опции способны предоставить огромное количество информации, которая определённо окажется полезной при проведении отладки самой BEAM, но не будем сейчас забивать этим голову.
2. Как получить информацию о модуле в интерактивной оболочке
Что мне нравится в Ruby, так это возможность вызвать метод methods
в любом объекте и получить список всех доступных для объекта методов. Когда я только начинал копаться в Ruby, это действие показалось мне невероятно удобным, и я до сих пор время от времени им пользуюсь.
Как же осуществить подобное в Elixir? Module.module_info
. Пример:
# defined in foo/bar/awesome.ex
defmodule Awesome do
def very_cool(arg) do
# ...
end
def beast_is_the_best_of_the_x_men, do: true
end
iex(4) Awesome.module_info(:exports)
[:beast_is_the_best_of_the_x_men/0, :very_cool/1]
Функция module_info
без всяких аргументов возвращает список ключевых слов с соответствующими им ключами: [:module, :attributes, :compile, :native, :md5]
. Любое из этих слов можно передать в качестве аргумента, чтобы поместить возвращаемое значение в область видимости.
Конечно, далеко не всё, что есть в Ruby, можно реализовать в Elixir.
3. Как определить функции в IEx
В интерактивной оболочке Ruby (и практически любого другого языка) можно определять функции верхнего уровня. Однако, если осуществить в IEx подобное:
iex(9)> def square(x) do
...(9)> x * x
...(9)> end
То получится следующее:
** (ArgumentError) cannot invoke def/2 outside module
(elixir) lib/kernel.ex:4297: Kernel.assert_module_scope/3
(elixir) lib/kernel.ex:3299: Kernel.define/4
(elixir) expanding macro: Kernel.def/2
iex:9: (file)
Существуют два способа определения функций в IEx. Первый — объявить анонимную функцию. Придётся вызывать её достаточно странным способом (такой синтаксис в Ruby безошибочен, но перегружен):
iex(8) square = fn (x) -> x * x end
iex(9) square.(20)
400
Второй способ — написать дополнительный модуль. Возможно, лучше будет пойти именно вторым путём, или даже начать писать код прямо в файл.
iex(10) defmodule Necessary do
...(10) def square (x) do
...(10) x * x
...(10) end
...(10) end
iex(10) Necessary.square(20)
400
4. Как скомпилировать код в файл
Допустим, имеется некий код, представляющий собой модуль. Можно скомпилировать его с помощью команды c
, указав после неё путь к файлу:
iex(3)> c "foo/bar/awesome.ex"
[Awesome]
После этого все модули, описанные в файле awesome.ex
станут доступными для использования.
5. Как добавить новые функции в модуль
Модули в Elixir не являются открытыми. Это значит, что, если попробовать определить уже существующий модуль defmodule AlreadyExistingModule ...
, он перепишется и будет содержать только новые функции. А ещё это значит, что «проманкипатчить» основной модуль тоже не получится.
Если же есть необходимость добавить новую функцию или переопределить старую, и при этом код хранится в файле, то можно дописать в него нужные строки и провести его компиляцию повторно командой r ModuleName
. Таким образом, при всех последующих вызовах методы будут содержать обновлённый код.
6. Как узнать о других доступных командах (бонус)
Для этого просто воспользуйтесь командой h
.
По синтаксису и набору инструментальных средств Elixir крайне схож с Ruby, но наряду с этим у него имеются и некоторые отличные особенности. Нужно заметить, что интерес к Elixir растёт, и это не может не радовать. Так почему бы вам не опробовать все описанное выше прямо сейчас?