什么是核心Erlang 'letrec'?

ubby3x7f  于 2022-12-08  发布在  Erlang
关注(0)|答案(1)|浏览(93)

Core Erlang的letrec是做什么用的?
理查德·卡尔松在"Introduction to Core Erlang"中写道:
此外,letrec表达式允许本地(递归)函数定义,而ERLANG本身没有,但在转换中通常很有用。
letrec对哪些转换有用?
当从Erlang翻译时,erlc实际上会生成letrec吗?还是只有当从非Erlang源语言翻译时才会生成letrec

dxxyhpgq

dxxyhpgq1#

Nowadays, list comprehensions are translated to letrecs (which are available in Core Erlang), and the letrecs are in turn translated to ordinary recursive functions.
请注意,"Today"是指2010年。此外,还有一些在EEP 52: Allow key and size expressions in map and binary matching中使用它的示例:
在OTP 23中,段大小表达式中使用的所有变量都必须已在封闭环境中绑定。必须使用嵌套的情况重写前面的示例,如下所示:

'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

但是,从示例中可以看出,引发function_clause异常的代码是重复的。在这个简单的示例中,代码重复不是什么大问题,但是在二进制匹配子句后面有许多其他子句的函数中,代码重复是很大的问题。为了避免代码重复,我们必须使用带有letrec_goto注解的letrec

'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'] )

相关问题