Модуль

Модуль — основной “кирпичик” нашего кода. То же: module.

В заголовке файла исходника мы обозначаем, что это за модуль:

-module(hello).

Модуль теперь имеет имя hello. Данное имя должно соответствовать имени файла, который проходит компиляцию. Если файл будет называться privet.erl, а не hello.erl, то компилятор выдаст ошибку.

Если в модуле hello мы создадим функцию test() и ее экспортируем, то снаружи мы эту функцию можем вызывать так:

hello:test()

Экспорт функции выглядит так:

-export([test/0]).

Это значит, что мы экспортируем функцию test/0. 0 означает, что эта функция принимает 0 параметров. Могут быть функции test/1, test/2 и т.д. Может быть так, что test/0 и test/1 — совершенно разные функции. И может быть так, что, например, test/1 это какая-то “рабочая лошадка”, которая нужна только для обслуживания других функций внутри этого файла. Поэтому мы её не экспортируем, а экспортируем только test/0.

Если мы желаем, чтобы все функции автоматически экспортировались из данного файла, вместо нескольких “-export()” можем поставить одну команду компилятору:

-compile(export_all).

Но компилятор Эрланга нам на всякий случай выдаст предупреждение — проявит, так сказать, озабоченность. Не забыли ли мы случайно, что и правда тут все функции экспортируются и станут доступны извне? Если это сообщение мешает, его можно отключить.

Скомпилированные модули можно запускать из оболочки.

Если в программе надо задействовать атом, обозначающий название модуля, можно не писать его прямо, а использовать ?MODULE. Препроцессор автоматически поменяет это на название модуля. Часто можно встретить, например, подобную строку: Ets = ets:new(?MODULE, [bag]),. Такая привычка хороша для открытия таблиц ETS, чтобы случайно не открыть таблицу, которая уже открыта в другом акторе.

Эрланг содержит довольно мощную стандартную библиотеку, включающую в себя 67 модулей. Один модуль может включать в себя несколько десятков функций.

Конечно, надо стараться случайно не создать модуль с именем как у системного. Если всё же случайно создать такой, то будет использоваться системный модуль. Если в системном модуле уже есть функция, которую мы запускаем, запустится именно она. Если нет такой функции (но она есть в нашем модуле с таким же именем), то будет ошибка: функция не определена.

Компиляция модуля начинается с работы epp — препроцессора, который раскрывает макросы и вставляет инклюды.

Для универсальной идентификации функции надо определить три вещи: модуль, функцию и арность. В общем виде это выглядит так:

Модуль:Функция/Арность

Пример: lists:seq/2. Именно в таком виде принято писать в документации по Эрлангу.

Пара слов про пунктуацию. Модуль включает в себя несколько функций, каждая функция заканчивается точкой. Функция состоит из нескольких кляуз, и между ними точки с запятыми. Кляуза состоит из нескольких выражений, и между ними — запятые.

Базовые (популярные) модули

Вместе с Эрлангом поставляется ряд очень полезных и просто иногда полезных модулей. Среди них, например:

Самым важным является модуль erlang, бифы из которого могут использоваться без указания модуля. Можно использовать, например, как erlang:date(), так и просто date().

Модули при спауне актора

Актор спаунится из конкретной функции. spawn/3, spawn_link/3, spawn_monitor/3 требуют указания модуля:

1> spawn(io, fwrite, ["Я помню..."]). 
Я помню...<0.101.0>
2> spawn_link(io, fwrite, ["Я помню..."]). 
Я помню...<0.103.0>
3> spawn_monitor(io, fwrite, ["Я помню..."]). 
Я помню...{<0.105.0>,#Ref<0.2749520132.163315714.17547>}
4> 

Здесь мы спауним банальную функцию io:fwrite/1, чтобы она выполнилась параллельно. io — название модуля. В квадратных скобках — аргумент.

Документация по модулю

Для поиска документации по конкретному модулю я обычно использую поисковик и там просто ввожу, например, “erlang re”. re — это модуль, отвечающий за регулярные выражения. Гугл как правило первой строкой выдаёт ссылку на документацию по данному модулю на erlang.org.

Можно посмотреть документацию по модулю прямо в оболочке:

1> h(re).

   re

  This module contains regular expression matching
  functions for strings and binaries.

  The regular expression syntax and semantics
  resemble that of Perl.

  The matching algorithms of the library are based on
  the PCRE library, but not all of the PCRE library is
  interfaced and some parts of the library go beyond
  what PCRE offers. Currently PCRE version 8.40
  (release date 2017-01-11) is used. The sections of
more (y/n)? (y) 

Если нужна справка по функции в модуле, используется h/2:

4> h(erlang,date).

  -spec date() -> Date when Date :: calendar:date().

  Returns the current date as {Year, Month, Day}.

  The time zone and Daylight Saving Time correction
  depend on the underlying OS. The return value is
  based on the OS System Time. Example:

    > date().
    {1995,2,19}
ok

© Алексей Карманов, 2024.