首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Erlang代码评论

问Erlang代码评论
EN

Stack Overflow用户
提问于 2010-04-18 04:25:37
回答 2查看 504关注 0票数 3

我正在尝试理解一些基本的erlang功能,我需要对以下内容做一些评论。

我有以下erlang代码,它接受一个元组列表,如果找到一个键,则返回一个减去一个元素的列表:

代码语言:javascript
复制
delete(Key, Database) ->
    remove(Database, Key, []).

remove([], Key, Acc) ->
    Acc;
remove([H|T], Key, Acc) ->
    if
        element(1, H) /= Key ->             
            [H| remove(T, Key, Acc)];
        true  -> 
            remove(T, Key, Acc)
    end.

这是一种很好的方式吗?

if语句似乎不正确。

另外,我使用累加器Acc会使这个尾部递归吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-04-18 06:35:51

不,您使用Acc并不会使其成为尾递归。您的if分支返回[H| remove(T, Key, Acc)],这不是尾部调用,并且此分支将在大部分时间内使用。更准确地说,您的Acc用法是无用的,因为它将一直是[],您根本不会更改它的值。正确的代码应该如下所示。

代码语言:javascript
复制
delete(Key, Database) ->
    remove(Database, Key, []).

remove([], Key, Acc) ->
    lists:reverse(Acc);
remove([H|T], Key, Acc) ->
    if
        element(1, H) /= Key ->             
            remove(T, Key, [H|Acc]);
        true  -> 
            remove(T, Key, Acc)
    end.

但是如果你的列表成员总是成对的,我更倾向于直接模式匹配:

代码语言:javascript
复制
delete(Key, Database) ->
    remove(Database, Key, []).

remove([], Key, Acc) ->
    lists:reverse(Acc);
remove([{Key, _}|T], Key, Acc) ->
    remove(T, Key, Acc);
% if it should delete only first occurrence then lists:reverse(Acc, T);
remove([H|T], Key, Acc) ->
    remove(T, Key, [H|Acc]).

但我认为这是一个可以应用Myth: Tail-recursive functions are MUCH faster than recursive functions的例子,所以我会使用更简单的递归版本:

代码语言:javascript
复制
delete(Key, []) -> [];
delete(Key, [{Key, _}|T]) -> delete(Key, T);
% if it should delete only first occurrence then just T;
delete(Key, [H|T]) -> [H | delete(Key, T)].
票数 5
EN

Stack Overflow用户

发布于 2010-04-19 00:13:33

如前所述,已经有一个标准的模块函数可以做到这一点(proplists:delete)。不需要多说,但是...

我倾向于保留原来的方法名(delete),但有一个包含累加器作为参数的本地版本。上下文让我认为元组在“数据库”中的顺序并不重要,因此列表:reverse是不必要的。

代码语言:javascript
复制
-module(foo).
-export([delete/2]).

delete(Key, Database) ->
    delete(Key, Database, []).

delete(_Key, [], Acc) ->
    Acc;
delete(Key, [{Key, _} | T], Acc) ->
    delete(Key, T, Acc);
delete(Key, [Entry={_, _} | T], Acc) ->
    delete(Key, T, [Entry | Acc]).

这里有几件事:

  • tail-recursive;总的来说,我认为使用尾递归更安全--虽然有针对主体递归调用的优化,但您确实需要对真实的(对于您的应用程序)数据进行一些性能测量,以生成一个我们在这里不接受任何旧列表的comparison
  • note;delete/3中的条目模式匹配有助于确保这一点(取决于它的用途,您可能想要它,也可能不想要它)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2659915

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档