我是二郎的全新人物。作为学习语言的练习,我尝试使用尾递归并且不使用sublist
来实现函数reverse
。以下是我从此网站http://learnyousomeerlang.com/recursion获取的功能:
tail_sublist(L, N) -> reverse(tail_sublist(L, N, [])).
tail_sublist(_, 0, SubList) -> SubList;
tail_sublist([], _, SubList) -> SubList;
tail_sublist([H|T], N, SubList) when N > 0 ->
tail_sublist(T, N-1, [H|SubList]).
似乎在erlang中使用reverse
非常频繁。
在Mozart / Oz中,使用未绑定变量创建此类函数非常容易:
proc {Sublist Xs N R}
if N>0 then
case Xs
of nil then
R = nil
[] X|Xr then
Unbound
in
R = X|Unbound
{Sublist Xr N-1 Unbound}
end
else
R=nil
end
end
是否可以在erlang中创建类似的代码?如果没有,为什么?
修改
我想澄清一下这个问题。 Oz中的函数不使用任何辅助函数(没有追加,没有反转,没有任何外部或BIF)。它也是使用尾递归构建的。
当我问是否可以在erlang中创建类似的东西时,我问是否可以使用尾递归在erlang中实现一个函数或一组函数,并且只在初始列表上迭代一次。
此时,在阅读了你的评论和答案之后,我怀疑它是否可以完成,因为erlang似乎不支持未绑定的变量。似乎所有变量都需要分配给值。
答案 0 :(得分:1)
这是一个使用附加的版本,而不是最后的反向。
subl(L, N) -> subl(L, N, []).
subl(_, 0, Accumulator) ->
Accumulator;
subl([], _, Accumulator) ->
Accumulator;
subl([H|T], N, Accumulator) ->
subl(T, N-1, Accumulator ++ [H]).
我不会说“在Erlang中使用反向非常频繁”。我会说reverse
的使用在函数式语言中的玩具问题中很常见,其中列表是一种重要的数据类型。
我不确定你试图用你的获得的Oz代码有多接近“是否可以在Erlang中创建类似的代码?如果没有,为什么?”他们是两个不同的语言,并做了许多不同的语法选择。
答案 1 :(得分:1)
短版
否,您在Erlang中没有类似的代码。原因是因为在Erlang中变量是Single assignment variables。 在Erlang中根本不允许使用未绑定的变量。
长版
我无法想象一个类似于上面提到的尾递归函数,因为你想要比较的两种语言的范式水平存在差异。
但是它也取决于你的意思是类似的代码。 所以,如果我错了,请纠正我,以下
R = X|Unbound
{Sublist Xr N-1 Unbound}
表示在递归调用返回 Unbound 的值之前,不会执行属性( R = X | Unbound )。 这对我来说看起来很像以下几点:
sublist(_,0) -> [];
sublist([],_) -> [];
sublist([H|T],N)
when is_integer(N) ->
NewTail = sublist(T,N-1),
[H|NewTail].
%% or
%%sublist([H|T],N)
%% when is_integer(N) -> [H|sublist(T,N-1)].
但是这段代码不是递归的。