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 #
true 和 false 是特殊的原子:
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