简体   繁体   English

Erlang中的另一种递归

[英]Different kind of recurrsions in erlang

I think it may be the pretty much basic question. 我认为这可能是非常基本的问题。 What are the different types of recursions that we use in the functional programming. 我们在函数式编程中使用哪些不同类型的递归。 And what kind of recursions that we use the programming language Erlang. 以及我们使用编程语言Erlang进行哪种递归。

我建议您阅读经典著作: http : //mitpress.mit.edu/sicp/特别是: 1.2程序及其生成的过程

I would recommend looking into Learn You Some Erlang since it is nice and comprehensive description of this topic. 我建议您研究“ 学习一些Erlang”,因为它是对本主题的很好而全面的描述。

In short there are two types, distinguished by semantics rather than syntax. 简而言之,有两种类型,通过语义而非语法来区分。

There is basic requisition one can see in almost any other language 人们几乎可以用任何其他语言看到基本的请购单

fibonacci ( 0 ) -> 
   0;
fibonacci ( 1 ) ->
   1;
fibonacci( X ) when X > 1 ->
   fibonacci( X-1 ) + fiboancci( X-2 ). 

And this is working with expected stack memory usage (new stack for almost each function call. 并且这与预期的堆栈内存使用情况(几乎每个函数调用都使用新堆栈)一起工作。

And there is something called tail recursion . 还有一种叫做尾递归的东西。 When recursive function is last being called, the compiler can skip creating new stack for each call, since there will be no need fir unwinding, returning back to higher level for any other logic. 当最后一次调用递归函数时,编译器可以跳过为每个调用创建新堆栈的步骤,因为不需要解散冷杉,对于其他任何逻辑,都可以返回更高的级别。 All that is need to done is to return a final value. 所有需要做的就是返回一个最终值。 To understand it better lets look deeper into our example. 为了更好地理解它,让我们更深入地研究我们的示例。

In fibonacci above, the last function being called is addition of two numbers. 在上面的fibonacci ,最后一个调用的函数是两个数的加法。 We could rewrite this function to use some kind of counter similar to for loops in other languages, and accumulator, which will be returned at the end ( B ) 我们可以重写此函数,以使用类似于其他语言中的for循环的某种计数器和累加器,这将在末尾( B )返回。

fibonacci(X) ->
    fibonacci( X, 0, 1).

fibonacci( 1, _A, B) ->
    B;
fibonacci( Counter, A, B ) ->
    fibonacci( Counter-1, B, A+B). 

This time function fibonacci/3 can be executed without stack unwinding . 时间函数fibonacci/3可以在不取消堆栈的情况下执行。 It's still recursion, with all the same rules and logic, but it is able to be run faster (and without so much memory consumption). 它仍然是递归的,具有相同的规则和逻辑,但是它可以运行得更快(并且没有太多的内存消耗)。

In Erlang this possibility of tail recursion have one important consequance. 在Erlang中,这种尾部递归的可能性有一个重要的后果。 It allows for long (forever) running processes. 它允许长时间(永远)运行的进程。 If you look at almost any actor with receive clause it fallows similar pattern 如果您几乎使用receive子句查看任何演员,就会发现相似的模式

loop(SomeState) ->
    receive 
        PatterMatch ->
            [ .. Do some stuff .. ]
            loop(UpdatedState);

        AnotherPatternMatch ->
            [.. different actions ..]
            loop(UpdatedStte);

        stop ->
            ok
    end.

You can easily notice that loop/1 function it recursive. 您可以轻松地注意到loop/1是递归的。 And fact that it is tali recursive allows it to be called time after time without increasing memory usage by this process. 它是tali递归的事实允许一次又一次地调用它,而不会增加此过程的内存使用量。

Written with StackEdit . StackEdit编写

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM