Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
167 views
in Technique[技术] by (71.8m points)

What is Core Erlang's `letrec` for?

What is Core Erlang's letrec for?

Richard Carlsson writes, in "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.

What transformations is letrec useful for?

Does erlc actually generate letrec when translating from Erlang? Or would letrecs only be generated when translating from a non-Erlang source language?

question from:https://stackoverflow.com/questions/65905246/what-is-core-erlangs-letrec-for

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Nowadays, list comprehensions are translated to letrecs (which are available in Core Erlang), and the letrecs are in turn translated to ordinary recursive functions.

Note that "Nowadays" is 2010. Also, there are some examples of its use in 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'] )

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...