查看源代码 即将到来的潜在不兼容性
引言
本文档列出了 Erlang/OTP 中计划的即将到来的潜在不兼容性。
OTP 27
Fun 创建者 pid 将始终是本地 init 进程
从 OTP 27 开始,函数 erlang:fun_info/1,2
将始终表明本地 init
进程创建了所有 fun,而不管 fun 最初是在哪个进程或节点上创建的。
在 OTP 28 中,{pid,_}
元素将完全删除。
feature maybe_expr 将默认启用
从 OTP 27 开始,maybe_expr
功能将被批准并默认启用。这意味着使用未加引号的原子 maybe
的代码将无法编译。所有将 maybe
用作原子的用法都需要加引号。或者,作为短期解决方案,可以禁用 maybe_expr
功能。
建议尽快引用所有原子 maybe
的用法。编译器选项 warn_keywords
可用于发出关于所有未加引号的 maybe
出现的警告。
0.0 和 -0.0 将不再完全相等
目前,浮点数 0.0
和 -0.0
具有不同的内部表示形式。如果将它们转换为二进制文件,就可以看到这一点
1> <<0.0/float>>.
<<0,0,0,0,0,0,0,0>>
2> <<-0.0/float>>.
<<128,0,0,0,0,0,0,0>>
但是,当它们相互匹配或使用 =:=
运算符进行比较时,它们被认为是相等的。因此,0.0 =:= -0.0
目前返回 true
。
在 Erlang/OTP 27 中,0.0 =:= -0.0
将返回 false
,并且将 0.0
与 -0.0
匹配将失败。当用作映射键时,0.0
和 -0.0
将被认为是不同的。
==
运算符将继续对 0.0 == -0.0
返回 true
。
为了帮助查找可能需要修改的代码,在 OTP 27 中,当与 0.0
匹配或使用 =:=
运算符将此值进行比较时,将出现新的编译器警告。可以通过与 +0.0
而不是 0.0
匹配来抑制此警告。
我们计划在 OTP 26.1 中引入相同的警告,但默认情况下会禁用该警告。
单例类型变量将变为编译时错误
在 Erlang/OTP 26 之前,编译器会静默接受以下规范
-spec f(Opts) -> term() when
Opts :: {ok, Unknown} | {error, Unknown}.
f(_) -> error.
在 OTP 26 中,编译器会发出警告,指出类型变量 Unknown
是未绑定的
t.erl:6:18: Warning: type variable 'Unknown' is only used once (is unbound)
% 6| Opts :: {ok, Unknown} | {error, Unknown}.
% | ^
在 OTP 27 中,该警告将变为错误。
Escripts 将默认编译
Escripts 将默认编译而不是解释。这意味着 compiler
应用程序必须可用。
可以通过将以下行添加到脚本文件中来恢复解释 escripts 的旧行为
-mode(interpret).
在 OTP 28 中,将删除对解释 escript 的支持。
-code_path_choice 将默认为 strict
此命令行选项控制命令行、引导脚本和代码服务器中给定的路径应被解释为严格还是宽松。
OTP 26 及更早版本默认为 relaxed
,这意味着 -pa myapp/ebin
将尝试加载 -pa myapp/ebin
和 -pa myapp/myapp/ebin
。该选项在 OTP 27 中将默认为 strict。
将删除归档回退
OTP 26 及更早版本允许应用程序将其部分目录作为常规文件夹,而将其余目录作为归档文件。此功能以前由 reltool 使用,但从 OTP 26 开始不再如此。从 OTP 27 的代码服务器中将删除对归档回退的支持。
三引号字符串
在 Erlang/OTP 27 之前,3 个或更多双引号字符的序列被分成对,每对都表示空字符串,如果存在奇数个,则最后一个字符是字符串的开头。然后,空字符串被连接起来并有效地消失了。
在 Erlang/OTP 27 中,3 个或更多双引号字符被解释为“三引号字符串”的开始。请参见 EEP 64。
以下是一些会改变含义的代码示例。请注意,在 Erlang/OTP 27.0 之前的所有这些示例都很奇怪,因为没有合理的理由这样写。
"""String Content"""
%% Was interpreted as
"" "String Content" ""
%% Which becomes
"String Content"
%%
%% In OTP 27 it is instead a syntax error since no text is allowed
%% on the line after an opening triple-quote
"""
String Content
"""
%% Was interpreted as
"" "
String Content
" ""
%% Which becomes
"
String Content
"
%%
%% In OTP 27 it is instead interpreted as a
%% Triple-Quoted String equivalent to
"String Content"
""""
++ foo() ++
""""
%% Became
"" ++ foo() ++ ""
%%
%% In OTP 27 it is instead interpreted as a
%% Triple-Quoted String (triple-or-more) equivalent to
"++ foo() ++"
从 Erlang/OTP 26.1 到 27.0,编译器会发出关于 3 个或更多双引号字符的序列的警告,因为这几乎肯定是一个错误,或者类似于糟糕的自动代码生成的结果。如果用户收到该警告,则应更正代码,例如通过在空字符串之间插入适当的空格,或完全删除冗余字符串,这将在 Erlang/OTP 27 之前和之后具有相同的含义。
OTP 28
re 模块将使用不同的正则表达式引擎
模块 re
的功能目前由 PCRE 库提供,该库不再被积极维护。因此,在 OTP 28 中,我们将切换到不同的正则表达式库。
re
模块使用的 PCRE 源代码已由 OTP 团队修改,以确保在匹配大型输入二进制文件和/或使用苛刻(回溯)正则表达式时正则表达式匹配会产生结果。由于这些修改,迁移到新版本的 PCRE 一直是一个耗时的过程,因为所有修改都必须再次手动应用于更新的 PCRE 源代码。
新的正则表达式库很可能是 RE2。RE2 保证匹配时间与输入字符串的长度呈线性关系,并且它还避免使用递归以防止堆栈溢出。这应该使在不修改其源代码的情况下使用 RE2 成为可能。有关为什么 RE2 是一个不错的选择的更多信息,请参阅 WhyRE2。
此更改的一些影响是
- 我们预计
re
模块中的函数将继续得到支持,尽管某些选项可能会被弃用。 - 很可能仅支持 UTF8 编码的二进制文件的模式匹配(不支持 Latin1 编码的二进制文件)。
- 为了保证线性时间性能,RE2 不支持 PCRE 中正则表达式模式中的所有构造。例如,不支持反向引用和环视断言。有关 RE2 支持的内容的描述,请参见 Syntax。
- 编译正则表达式可能会比较慢,因此通过在匹配之前显式编译正则表达式可以获得更多好处。
Fun 创建者 pid 将被删除
从 OTP 28 开始,函数 erlang:fun_info/1
将不包含 {pid,_}
元素,函数 erlang:fun_info/2
将不再接受 pid
作为第二个参数。
将删除对解释 escripts 的支持
Escripts 将被编译,并且不再可能使用指令 -mode(interpret)
强制解释 escript。
OTP 29
将不再可能禁用 feature maybe_expr
从 OTP 29 开始,maybe_expr
功能将成为永久性的,不再可能禁用。所有将 maybe
用作原子的用法都需要加引号。
建议尽快引用所有原子 maybe
的用法。编译器选项 warn_keywords
可用于发出关于所有未加引号的 maybe
出现的警告。
cprof 和 eprof 将被 tprof 取代
从 OTP 29 开始,将删除 cprof
和 eprof
,而采用 OTP 27 中添加的 tprof
。