erlang - Erlang 中的尾递归

我真的很难理解 Erlang 中的尾递归。

我有以下 eunit 测试:

db_write_many_test() ->
    Db = db:new(),
    Db1 = db:write(francesco, london, Db),
    Db2 = db:write(lelle, stockholm, Db1),
    ?assertEqual([{lelle, stockholm},{francesco, london}], Db2).

这是我的实现:

-module(db) .
-include_lib("eunit/include/eunit.hrl").
-export([new/0,write/3]).

new() ->
    [].

write(Key, Value, Database) ->
    Record = {Key, Value},
    [Record|append(Database)].

append([H|T]) ->
    [H|append(T)];  
append([])  ->
    [].

我的实现是尾递归的吗?如果不是,我该如何实现?

提前致谢

最佳答案

您的实现不是尾递归的,因为在计算尾部时追加必须保持在列表的头部。为了使函数成为尾递归函数,返回值不得依赖于函数调用返回的值以外的值。

你可以这样重写它:

append(Acc, []) -> %% termination;
    Acc;
append(Acc, [H|T]) ->
    Acc2 = Acc ++ dosomethingto(H); %% maybe you meant this to be your write function?
    append(Acc2, T); %% tail rercursive

请注意,一旦发生尾递归调用,所有工作就完成了。所以追加函数可以忘记函数体中的所有内容,只需要记住它传递给下一个调用的参数值。

另请注意,我将终止子句放在递归子句之前。 Erlang 按顺序评估子句,并且由于终止子句通常更具体,不太具体的递归子句将隐藏它们,从而防止函数返回,这很可能不是您想要的行为。

https://stackoverflow.com/questions/2658631/

相关文章:

python - 压缩存档,可快速访问单个文件

c# - 以特定时间间隔从视频(mpg、wmv 等)中捕获帧

git - 如何使用 ssh 将 repo 克隆到远程服务器

ruby-on-rails - rails : Expected helper to define

asp.net-mvc - ASP.Net MVC 2.0 : unescaping URL que

apache - 在 ReverseProxy 上下文中切换 SSLVerifyClient

sql-server - SQL 错误 : Verify that the instance nam

python - python 中的 Rfc 1123

open-source - 用于检测运行笔迹的开源

modeling - Data Vault 模型什么时候是数据仓库的正确模型?