Пространства имен и записи в erlang

Erlang, очевидно, имеет понятие пространства имен, мы используем такие вещи, как application: start() каждый день.

Я хотел бы знать, существует ли такая вещь, как пространство имен для записей. В моем приложении я определил запись user. Все было в порядке, пока мне не потребовалось включить rabbit.hrl из rabbitmq, который также определяет user, что противоречит моей.

Поиск в Интернете не помог решить эту проблему. Я рассмотрел переименование моей учетной записи пользователя и префикс ее чем-то, скажем, "myapp_user". Это исправит эту конкретную проблему, пока я не подозреваю, что ударил другой конфликт с помощью моей записи "сеанс".

Каковы мои варианты здесь? Добавляет ли префикс "myapp_" ко всем моим записям хорошую практику или существует реальная поддержка пространств имен с записями, и я просто не нахожу ее?

EDIT: Спасибо всем за ваши ответы. Я узнал, что записи являются глобальными. Принятый ответ дал понять. Я поеду с добавлением префиксов ко всем моим записям, как я и ожидал.

Ответ 1

Я бы сказал, что у Erlang нет пространств имен. Модули являются глобальными (за исключением очень непопулярного расширения для языка), имена являются глобальными (либо для node, либо для кластера), pids являются глобальными, порты глобальны, глобальные ссылки и т.д.

Все заложено. Таким образом, пространство имен в Эрланге выполняется условно, а не любое другое среднее. Вот почему в именах модулей есть <appname>_app, <appname>_sup и т.д. Зарегистрированные процессы также, вероятно, следуют этой схеме, таблицам ETS и т.д.

Однако вы должны отметить, что сами записи не являются глобальными: как JUST MY correct OPNION, это просто компилятор трюков за кортежи. Из-за этого они локальны для определения модуля. Никто за пределами модуля не увидит запись, если они также не включают определение записи (либо путем ее копирования, либо с помощью файла заголовка, а позднее - лучший способ сделать это).

Теперь я мог бы утверждать, что, поскольку вам нужно включать .hrl файлы и определения записи для каждого модуля, нет такой вещи, как записи с именами; они скорее охвачены модулем, как переменная. Нет никаких оснований для их пространственного пространства: просто включите правильный.

Конечно, это может быть случай, когда вы включаете определения записей из двух модулей, и обе записи имеют одинаковое имя. Если это произойдет, может потребоваться переименование записей с префиксом, но это довольно редкое явление в моем опыте.

Обратите внимание, что это также, как правило, плохая идея для публикации записей в других модулях. Одна из проблем заключается в том, что все модули, зависящие от ваших, теперь включают в себя файл .hrl. Если ваш модуль изменит определение записи, вам придется перекомпилировать каждый другой модуль, который зависит от него. Лучшей практикой должно быть внедрение функций для взаимодействия с данными. Обратите внимание, что get (Key, Struct) не всегда является хорошей идеей. Если вы можете выбрать значащие имена (возраст, имя, дети и т.д.), Ваш код и API должны иметь больше смысла для читателей.

Ответ 2

Вам нужно будет либо назвать все ваши записи способом, который вряд ли будет конфликтовать с другими записями, либо вам просто не нужно использовать их для разных модулей. В большинстве случаев я буду рассматривать записи как непрозрачные структуры данных и добавлять функциональные возможности модуля, который определяет запись для доступа к ней. Это позволит избежать проблемы, с которой вы столкнулись.

Ответ 3

Я могу сказать, что я даю ТЕРРОМУ СОВЕТУ здесь с его глубоким знанием Эрланг, но я уверен, что в Эрланге нет пространств имен для записей. Имя записи - всего лишь атом, привитый на переднюю часть кортежа, который компилятор строит для вас за кулисами. (Записи в значительной степени просто взломать кортежи, вы видите.) После компиляции там нет значимого пространства имен для записи.

Например, посмотрим на эту запись.

-record(branch, {element, priority, left, right}).

Когда вы создаете экземпляр этой записи в коде...

#branch{element = Element, priority = Priority, left = nil, right = nil}.

... то, что выходит на другом конце, есть кортеж, подобный этому:

{branch, Element, Priority, nil, nil}

То, что все записи в данный момент. Там нет фактического объекта записи и, следовательно, пространство имен не имеет никакого смысла. Название записи - это просто атом, прикрепленный к фронту. В Erlang для меня вполне приемлемо иметь этот кортеж, а другой выглядит так:

{branch, Twig, Flower}

На уровне времени выполнения нет проблем с наличием обоих из них.

Но...

Конечно, есть проблема с тем, что в вашем коде есть записи, поскольку компилятор не знает, к какому branch я имею в виду, когда я создаю экземпляр. Вы должны, короче говоря, использовать ручную namespacing, о которой вы говорили, если вы хотите, чтобы записи отображались в вашем API.

Тем не менее, последняя точка - это ключ. Почему вы публикуете записи в своем API? Код, который я взял из моей записи, использует запись как чисто непрозрачный тип данных. У меня есть функция для создания записи ветки и , что - это то, что будет в моем API, если я хочу вообще открыть ветку. Функция принимает значения element, priority и т.д. И возвращает запись (чтение: кортеж). Пользователю не нужно знать о содержании. Если бы у меня был модуль, демонстрирующий (биологическую) древовидную структуру, он тоже мог бы вернуть кортеж, который, как оказалось, имеет атом branch как его первый элемент без какого-либо конфликта.

Лично, по моим вкусам, разоблачение записей в API Erlang - это запах кода. Иногда это может быть необходимо, но большую часть времени он должен оставаться скрытым.

Ответ 4

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