Фирменная оболочка (shell) Эрланга запускается с помощью команды erl.
$ erl
Erlang/OTP 25 [erts-13.1.5] [source] [64-bit] [smp:8:4]
[ds:8:4:10] [async-threads:1] [jit:ns]
Eshell V13.1.5 (abort with ^G)
1>
Из выведенной информации мы видим, например, что у нас Erlang/OTP 25. Установку мы провели из репозитория Debian, поэтому у нас не самая свежая версия Эрланга. На сайте erlang.org была уже доступна версия 26 (а точнее 26.1).
С помощью 1>
оболочка предлагает нам что-нибудь ввести. 1 — это номер линии. Потом будет 2, 3 и т.д. Для начала введём что-нибудь совсем простенькое:
1> 1 + 2 * 5.
11
2> 12 / 3.
4.0
С оболочкой можно делать много интересных вещей. Для начала её можно использовать как весьма удобный калькулятор.
3> Dlina = 7 + 3.5.
10.5
4> Dlina.
10.5
5> Shirina = 4 - 1.
3
6> Dlina * Shirina.
31.5
Было бы желание — и этот “калькулятор” можно сделать невероятно мощным. Находясь в оболочке, мы словно находимся внутри компьютерной программы.
Со временем, когда вы освоите множество бифов, их можно будет применять для всяких утилитарных целей. Допустим, если надо быстро посчитать количество символов в строке:
1> length("Я помню чудное мгновенье: Передо мной явилась ты...").
51
2>
Когда освоите обработчик списка, сможете одной командой вывести все високосные годы 19-го века или любого другого периода (1900 г. по правилам не считается високосным):
1> [ X || X <- lists:seq(1801, 1900),
calendar:last_day_of_the_month(X,2) > 28 ].
[1804,1808,1812,1816,1820,1824,1828,1832,1836,1840,1844,
1848,1852,1856,1860,1864,1868,1872,1876,1880,1884,1888,1892,
1896]
2>
Если в текущем каталоге (или другом каталоге, в котором Эрланг ищет модули) у нас есть соответствующий скомпилированный модуль с экспортированными функциями, мы можем вызвать их. В следующем примере: мы вызываем модуль k, который сами написали и скомпилировали, и в нём функцию fact() для подсчёта факториала.
7> k:fact(5).
120
Из оболочки можно любую функцию заспаунить как актора, и тогда эта функция будет выполняться параллельно. Мы можем послать этому актору сообщение, и если он ещё жив и умеет обрабатывать сообщения, он ответит.
9> spawn(io, fwrite, ["Я помню..."]).
Я помню...<0.96.0>
10> <0.96.0> ! privet.
Сама оболочка для Системы это тоже актор.
Если мы имеем развёрнутую на многих компьютерах Систему, то можем ею управлять из оболочки.
Оболочка помогает с автозавершением. Начав вводить название какого-либо модуля и нажав Tab, можно увидеть доступные варианты. Закончив вводить название модуля и поставив двоеточие, с помощью той же клавиши Tab, можно увидеть все доступные функции из этого модуля.
Оболочка хорошо помогает в изучении Эрланга — для понимания базовых вещей. Например, увидеть, что значение у атома — он сам:
1> privet.
privet
Если со временем забыли, например, как работают регулярные выражения, то можно тут же в оболочке вспомнить, потренироваться.
Не стоит слишком полагаться на оболочку при изучении Эрланга на первых этапах — может возникнуть недопонимание. Для полноценного понимания надо взять любимый текстовый редактор или IDE и там писать полноценный код. Только так можно понять, как вообще в целом работают функции, как срабатывают кляузы и т.д.
Если мы в оболочке напишем имя переменной и поставим после неё точку, то оболочка выведет значение этой переменной. И вообще любое валидное выражение с точкой воспринимается оболочкой как “нормальная” команда. Мы как бы командуем оболочкой: сделай это, выведи то… Внутри полноценного кода таких “команд” нет, там функции. Поэтому не следует путать пунктуацию в оболочке с пунктуацией в программе.
В оболочке удобно смотреть документацию по модулям и функциям в них. h(lists)
выведет информацию по модулю lists. h(lists, seq)
покажет справку по всем функциям seq (разной арности). h(lists, seq, 3)
проинформирует нас о функции seq/3 в модуле lists.
Если вы впервые зашли в оболочку Эрланга, у вас может возникнуть резонный вопрос: а как из неё выйти? Для этого и кое-чего другого есть встроенные команды:
Не забываем после всех команд ставить точку.
В стандартной библиотеке есть несколько модулей, ориентированных на оболочку:
Все команды оболочки, например ls()
, определены в модуле shell_default. Та же команда ls()
, например, может быть вызвана как shell_default:ls()
. Если мы желаем расширить арсенал этих команд (которые можно набирать без указания модуля), можно создать свой модуль. Название у модуля должно быть user_default.
-module(user_default).
-compile(export_all). % нам всё понадобится
te() ->
Sens = os:cmd("sensors"),
{match,[_,{Start,_}]} = re:run(Sens, "CPU Temperature: +\+(....)"),
Temp = string:slice(Sens, Start+1, 4),
io:format("+~ts °C~n", [Temp]).
fi(What) ->
Find = os:cmd("find . -name \""++What++"\""),
io:format("~ts~n", [Find]).
Мы сделали две собственные команды. te()
выдаёт температуру процессора, воспользовавшись системной командой sensors
. fi(What)
это обёртка над другой системной командой — find
. С помощью неё можно искать файлы в текущем каталоге, включая подкаталоги.
2> l(user_default).
{module,user_default}
3> te().
+40.0 °C
ok
4> fi("*.png").
./lib/wx-2.4.2/priv/erlang-logo64.png
./lib/wx-2.4.2/priv/erlang-logo32.png
./lib/wx-2.4.2/priv/erlang-logo128.png
./lib/wx-2.4.2/examples/demo/erlang.png
./lib/observer-2.16/priv/erlang_observer.png
./lib/debugger-5.4/priv/erlang_bug.png
./lib/edoc-1.3.1/priv/erlang.png
ok
В силу каких-то причин автоматически модуль user_default не загружается, хотя его beam-файл и доступен. Поэтому нам пришлось его загрузить с помощью l(user_default)
.
© Алексей Карманов, 2024.