Erlang原子 #

一、原子概述 #

原子(Atom)是Erlang中的一种基本数据类型,表示字面量常量。原子就是它自己的名字,它的值就是它本身。

1.1 原子的特点 #

  • 原子是全局唯一的
  • 原子不会被垃圾回收
  • 原子比较非常高效
  • 原子常用于表示状态、消息类型等

二、原子定义 #

2.1 简单原子 #

以小写字母开头:

erlang
-module(simple_atoms).
-export([demo/0]).

demo() ->
    ok,
    error,
    true,
    false,
    undefined,
    io:format("ok = ~p~n", [ok]),
    io:format("error = ~p~n", [error]),
    ok.

2.2 引号原子 #

包含特殊字符时使用单引号:

erlang
-module(quoted_atoms).
-export([demo/0]).

demo() ->
    WithSpace = 'Hello World',
    WithHyphen = 'content-type',
    WithDot = 'www.example.com',
    Empty = '',
    io:format("'Hello World' = ~p~n", [WithSpace]),
    io:format("'content-type' = ~p~n", [WithHyphen]),
    io:format("'www.example.com' = ~p~n", [WithDot]),
    io:format("'' = ~p~n", [Empty]),
    ok.

2.3 原子命名规则 #

erlang
-module(atom_rules).
-export([valid/0, invalid/0]).

valid() ->
    ok,
    my_atom,
    'MyAtom',
    atom123,
    'with-hyphen',
    'with space',
    ok.

invalid() ->
    ok.

有效原子

  • 小写字母开头:ok, error, my_atom
  • 引号包围:'Hello World', 'content-type'

无效原子

  • 大写字母开头(会被识别为变量):Ok, Error
  • 数字开头:123abc

三、布尔原子 #

3.1 true和false #

truefalse 是特殊的原子:

erlang
-module(boolean_atoms).
-export([demo/0]).

demo() ->
    io:format("true is atom: ~p~n", [is_atom(true)]),
    io:format("false is atom: ~p~n", [is_atom(false)]),
    io:format("true == true: ~p~n", [true == true]),
    io:format("true == false: ~p~n", [true == false]),
    ok.

3.2 在条件中使用 #

erlang
-module(boolean_usage).
-export([is_positive/1, classify/1]).

is_positive(N) when N > 0 -> true;
is_positive(_) -> false.

classify(N) ->
    case is_positive(N) of
        true -> positive;
        false -> non_positive
    end.

四、常用原子 #

4.1 状态原子 #

erlang
-module(status_atoms).
-export([process/1]).

process({status, ok}) ->
    io:format("Operation succeeded~n");
process({status, error}) ->
    io:format("Operation failed~n");
process({status, pending}) ->
    io:format("Operation pending~n");
process({status, timeout}) ->
    io:format("Operation timed out~n");
process(_) ->
    io:format("Unknown status~n").

常用状态原子:

  • ok - 成功
  • error - 错误
  • undefined - 未定义
  • pending - 待处理
  • timeout - 超时
  • skip - 跳过
  • ignore - 忽略

4.2 消息类型原子 #

erlang
-module(message_atoms).
-export([handle/1]).

handle({ping, From}) ->
    From ! pong,
    ok;
handle({request, From, Data}) ->
    Result = process_data(Data),
    From ! {response, Result},
    ok;
handle({stop, Reason}) ->
    io:format("Stopping: ~p~n", [Reason]),
    stopped.

process_data(Data) -> {processed, Data}.

4.3 配置原子 #

erlang
-module(config_atoms).
-export([get_config/1]).

get_config(mode) -> production;
get_config(level) -> debug;
get_config(encoding) -> utf8;
get_config(timeout) -> 5000;
get_config(_) -> undefined.

五、原子函数 #

5.1 类型检测 #

erlang
1> is_atom(ok).
true
2> is_atom('Hello World').
true
3> is_atom("hello").
false
4> is_atom(42).
false

5.2 原子与列表转换 #

erlang
-module(atom_list_conv).
-export([demo/0]).

demo() ->
    Atom = hello,
    List = atom_to_list(Atom),
    io:format("atom_to_list(hello) = ~p~n", [List]),
    
    NewAtom = list_to_atom("world"),
    io:format("list_to_atom(\"world\") = ~p~n", [NewAtom]),
    
    ExistingAtom = list_to_existing_atom("ok"),
    io:format("list_to_existing_atom(\"ok\") = ~p~n", [ExistingAtom]),
    ok.
函数 说明
atom_to_list/1 原子转列表
list_to_atom/1 列表转原子
list_to_existing_atom/1 列表转已存在原子

5.3 原子与二进制转换 #

erlang
-module(atom_binary_conv).
-export([demo/0]).

demo() ->
    Atom = hello,
    Binary = atom_to_binary(Atom, utf8),
    io:format("atom_to_binary(hello, utf8) = ~p~n", [Binary]),
    
    NewAtom = binary_to_atom(<<"world">>, utf8),
    io:format("binary_to_atom(<<\"world\">>, utf8) = ~p~n", [NewAtom]),
    
    ExistingAtom = binary_to_existing_atom(<<"ok">>, utf8),
    io:format("binary_to_existing_atom(<<\"ok\">>, utf8) = ~p~n", [ExistingAtom]),
    ok.
函数 说明
atom_to_binary/2 原子转二进制
binary_to_atom/2 二进制转原子
binary_to_existing_atom/2 二进制转已存在原子

5.4 list_to_existing_atom安全性 #

erlang
-module(safe_atom).
-export([safe_to_atom/1]).

safe_to_atom(List) when is_list(List) ->
    try
        list_to_existing_atom(List)
    catch
        error:badarg ->
            {error, atom_not_found}
    end.

六、原子比较 #

6.1 相等比较 #

erlang
1> ok == ok.
true
2> ok =:= ok.
true
3> ok == 'ok'.
true

6.2 排序比较 #

原子按字典序排序:

erlang
1> a < b.
true
2> abc < abd.
true
3> 'A' < 'a'.
true
4> aa < ab.
true

6.3 类型排序 #

不同类型的排序顺序:

erlang
number < atom < reference < fun < port < pid < tuple < map < nil < list < bitstring
erlang
1> 1 < atom.
true
2> atom < {tuple}.
true
3> {tuple} < [list].
true

七、原子在模式匹配中 #

7.1 标签模式 #

erlang
-module(tagged_tuples).
-export([handle/1]).

handle({ok, Result}) ->
    io:format("Success: ~p~n", [Result]);
handle({error, Reason}) ->
    io:format("Error: ~p~n", [Reason]);
handle({warning, Message}) ->
    io:format("Warning: ~p~n", [Message]);
handle(Other) ->
    io:format("Unknown: ~p~n", [Other]).

7.2 消息匹配 #

erlang
-module(message_matching).
-export([loop/0]).

loop() ->
    receive
        {ping, From} ->
            From ! pong,
            loop();
        {stop, Reason} ->
            io:format("Stopping: ~p~n", [Reason]),
            stopped;
        {data, Data} ->
            io:format("Data: ~p~n", [Data]),
            loop()
    end.

7.3 状态机 #

erlang
-module(state_machine).
-export([start/0]).

start() -> idle().

idle() ->
    receive
        connect -> connected();
        stop -> stopped
    end.

connected() ->
    receive
        disconnect -> idle();
        send_data -> 
            io:format("Sending data...~n"),
            connected();
        stop -> stopped
    end.

八、原子使用注意事项 #

8.1 原子不会被回收 #

警告:原子一旦创建,永远不会被垃圾回收!

erlang
-module(atom_danger).
-export([danger/1]).

danger(N) ->
    List = lists:seq(1, N),
    [list_to_atom("atom_" ++ integer_to_list(X)) || X <- List],
    ok.

如果N很大,会导致原子表溢出:

text
=ERROR REPORT==== 27-Mar-2026::10:00:00 ===
Too many atoms

8.2 原子表限制 #

默认原子表限制为 1,048,576 个原子:

erlang
1> erlang:system_info(atom_limit).
1048576
2> erlang:system_info(atom_count).
500

8.3 安全使用原子 #

erlang
-module(safe_atom_usage).
-export([safe_convert/1]).

safe_convert(String) when is_list(String) ->
    case is_safe_atom(String) of
        true -> {ok, list_to_existing_atom(String)};
        false -> {error, unsafe}
    end.

is_safe_atom(String) ->
    SafeAtoms = [ok, error, true, false, undefined],
    lists:member(String, [atom_to_list(A) || A <- SafeAtoms]).

8.4 使用二进制代替动态原子 #

erlang
-module(binary_instead).
-export([process/1]).

process(Key) when is_binary(Key) ->
    case Key of
        <<"ok">> -> handle_ok();
        <<"error">> -> handle_error();
        Other -> handle_other(Other)
    end.

handle_ok() -> ok.
handle_error() -> error.
handle_other(Key) -> {unknown, Key}.

九、原子最佳实践 #

9.1 使用有意义的名称 #

erlang
-module(meaningful_atoms).
-export([process/1]).

process({user_action, login}) -> handle_login();
process({user_action, logout}) -> handle_logout();
process({system_event, start}) -> handle_start();
process({system_event, stop}) -> handle_stop().

handle_login() -> ok.
handle_logout() -> ok.
handle_start() -> ok.
handle_stop() -> ok.

9.2 使用标签元组 #

erlang
-module(tagged_results).
-export([divide/2]).

divide(_A, 0) -> {error, division_by_zero};
divide(A, B) -> {ok, A / B}.

9.3 定义常量宏 #

erlang
-module(atom_macros).
-export([process/1]).

-define(STATUS_OK, ok).
-define(STATUS_ERROR, error).
-define(STATUS_PENDING, pending).

process(?STATUS_OK) -> success;
process(?STATUS_ERROR) -> failure;
process(?STATUS_PENDING) -> waiting.

9.4 使用include文件 #

erlang
-module(using_include).
-include("constants.hrl").
-export([process/1]).

process(?OK) -> success;
process(?ERROR) -> failure.

constants.hrl:

erlang
-define(OK, ok).
-define(ERROR, error).
-define(UNDEFINED, undefined).

十、总结 #

本章学习了:

  • 原子的定义和特点
  • 原子的命名规则
  • 布尔原子
  • 常用原子
  • 原子函数
  • 原子比较
  • 原子在模式匹配中的应用
  • 原子使用注意事项
  • 原子最佳实践

准备好学习字符串类型了吗?让我们进入下一章。

最后更新:2026-03-27