Я согласен с ответом camccann, что он, вероятно, отсутствует в основном потому, что его нужно было бы внедрить довольно глубоко в реализацию, и он слишком мал для использования на этом уровне сложности.В Erlang (и Prolog и Lisp) символы (или атомы) обычно служат специальными маркерами и служат в основном тем же понятием, что и конструктор.В Лисп динамическая среда включает в себя компилятор, поэтому это также (полезная) концепция компилятора, просочившаяся во время выполнения.
Проблема в следующем, интернирование символов нечисто (оно модифицирует таблицу символов).Поскольку мы никогда не модифицируем существующий объект, он, однако, прозрачен по ссылкам, но если реализован наивно, может привести к утечкам пространства во время выполнения.На самом деле, как в настоящее время реализовано в Erlang, вы можете фактически вывести из строя виртуальную машину, перепутав слишком много символов / атомов (я думаю, что текущий предел составляет 2 ^ 20), потому что они никогда не могут собрать мусор.Это также трудно реализовать в параллельной установке без огромной блокировки вокруг таблицы символов.
Однако обе проблемы могут быть (и были) решены.Например, см. Erlang EEP 20 .Я использую эту технику в пакете simple-atom .Он использует unsafePerformIO
под капотом, но только (надеюсь) в редких случаях.Он все еще может использовать некоторую помощь от GC для выполнения оптимизации, аналогичной сокращению косвенного обращения.Он также использует довольно много IORef
с внутренней стороны, что не слишком хорошо для производительности и использования памяти.
Таким образом, это можно сделать, но правильно реализовать его нетривиально.Авторы компиляторов всегда сравнивают возможности функции с усилиями по ее реализации и обслуживанию, и кажется, что первоклассные символы проигрывают в этом.