Core Erlang 的 `letrec` 有什么用?
What is Core Erlang's `letrec` for?
Core Erlang 的 letrec
有什么用?
Richard Carlsson 在 "Introduction to Core Erlang" 中写道:
Furthermore letrec
expressions allow local (recursive) function definitions, which ERLANG itself does not have, but which are often useful in transformations.
letrec 对哪些转换有用?
从 Erlang 翻译时 erlc
是否实际生成 letrec
?或者只有从非 Erlang 源语言翻译时才会生成 letrec
s?
请注意,“现在”是 2010 年。另外,在 EEP 52: Allow key and size expressions in map and binary matching 中有一些使用示例:
In OTP 23, all variables used in a segment size expression must be already
bound in the enclosing environment. The previous example must be rewritten
like this using nested cases:
'foo'/1 =
fun (_0) ->
case _0 of
<#{#<Sz>(16,1,'integer',['unsigned'|['big']]),
#<_2>('all',1,'binary',['unsigned'|['big']])}#> when 'true' ->
case _2 of
<#{#<X>(Sz,1,'integer',['unsigned'|['big']])}#> when 'true' ->
X
<_3> when 'true' ->
%% Raise function_clause exception.
.
.
.
end
<_4> when 'true' ->
%% Raise function_clause exception.
.
.
.
end
However, as can be seen from the example, the code for raising the function_clause
exception has been duplicated. The code duplication is no big deal in this simple
example, but it would be in a function where the binary matching clause was followed
by many other clauses. To avoid the code duplication, we must use letrec
with
the letrec_goto
annotation:
'foo'/1 =
fun (_0) ->
( letrec
'label^0'/0 =
fun () ->
case _0 of
<_1> when 'true' ->
%% Raise function_clause exception.
.
.
.
end
in case _0 of
<#{#<Sz>(16,1,'integer',['unsigned'|['big']]),
#<_2>('all',1,'binary',['unsigned'|['big']])}#> when 'true' ->
case _2 of
<#{#<X>(Sz,1,'integer',['unsigned'|['big']])}#> when 'true' ->
X
<_3> when 'true' ->
apply 'label^0'/0()
end
<_4> when 'true' ->
apply 'label^0'/0()
end
-| ['letrec_goto'] )
Core Erlang 的 letrec
有什么用?
Richard Carlsson 在 "Introduction to Core Erlang" 中写道:
Furthermore
letrec
expressions allow local (recursive) function definitions, which ERLANG itself does not have, but which are often useful in transformations.
letrec 对哪些转换有用?
从 Erlang 翻译时 erlc
是否实际生成 letrec
?或者只有从非 Erlang 源语言翻译时才会生成 letrec
s?
请注意,“现在”是 2010 年。另外,在 EEP 52: Allow key and size expressions in map and binary matching 中有一些使用示例:
In OTP 23, all variables used in a segment size expression must be already bound in the enclosing environment. The previous example must be rewritten like this using nested cases:
'foo'/1 = fun (_0) -> case _0 of <#{#<Sz>(16,1,'integer',['unsigned'|['big']]), #<_2>('all',1,'binary',['unsigned'|['big']])}#> when 'true' -> case _2 of <#{#<X>(Sz,1,'integer',['unsigned'|['big']])}#> when 'true' -> X <_3> when 'true' -> %% Raise function_clause exception. . . . end <_4> when 'true' -> %% Raise function_clause exception. . . . end
However, as can be seen from the example, the code for raising the
function_clause
exception has been duplicated. The code duplication is no big deal in this simple example, but it would be in a function where the binary matching clause was followed by many other clauses. To avoid the code duplication, we must useletrec
with theletrec_goto
annotation:'foo'/1 = fun (_0) -> ( letrec 'label^0'/0 = fun () -> case _0 of <_1> when 'true' -> %% Raise function_clause exception. . . . end in case _0 of <#{#<Sz>(16,1,'integer',['unsigned'|['big']]), #<_2>('all',1,'binary',['unsigned'|['big']])}#> when 'true' -> case _2 of <#{#<X>(Sz,1,'integer',['unsigned'|['big']])}#> when 'true' -> X <_3> when 'true' -> apply 'label^0'/0() end <_4> when 'true' -> apply 'label^0'/0() end -| ['letrec_goto'] )