是否可以在Erlang中创建未绑定的变量?
我对erlang是个全新的人。作为学习该语言的练习,我尝试使用尾部递归实现函数是否可以在Erlang中创建未绑定的变量?,erlang,tail-recursion,Erlang,Tail Recursion,我对erlang是个全新的人。作为学习该语言的练习,我尝试使用尾部递归实现函数子列表,而不使用反向。以下是我从该网站获得的功能: 在erlang中使用reverse似乎非常频繁 在Mozart/Oz中,使用未绑定变量创建这样的函数非常容易: proc {Sublist Xs N R} if N>0 then case Xs of nil then R = nil [] X|Xr then Unbound
子列表
,而不使用反向
。以下是我从该网站获得的功能:
在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似乎不支持未绑定变量。似乎所有的变量都需要赋值。这里有一个版本,它在执行过程中使用了附加项,而不是在末尾使用反向项
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中创建类似的代码?如果没有,为什么?”有多接近。它们是两种不同的语言,并且有许多不同的语法选择。短版本
否,在Erlang中不能有类似的代码。原因是在Erlang中,变量是。
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)].
但是这段代码不是尾部递归的。请参阅在尾部递归函数中使用reverse是个好主意。如果你能在不使用它的情况下有效地实现同样的结果,我认为使用反向
不是一个好主意。使用列表:如果你需要在顺序重要的地方使用列表,反向肯定是一个好主意。看来你没有花足够的时间去理解努诺所指的主题。无论如何,出于教学目的,自己动手做是一个非常好的主意。如果要提高效率,使用列表:子列表/2…使用反向不仅是一个好主意。这似乎是有效实现该功能的唯一方法。在erlang中使用列表似乎不可能做得更好。虽然我花了时间阅读另一个问题的答案,但它并没有回答我自己的问题。我不是问reverse
是否有效,也不是问为什么reverse
是个好主意。我想问的是,是否有可能在不使用reverse
的情况下高效地实现代码。在Oz中,我不需要使用任何辅助函数,实现使用尾部递归。在erlang中也可以这样做吗?我希望避免使用串联,对于一个很长的列表,最好使用reverse
。在Oz代码中,您不需要使用append来实现相同的结果。感谢您花时间阅读问题,甚至编写代码:)好的,我在Erlang方面没有太多经验,但我认为答案是Erlang并没有针对大规模链表的操作进行优化。Erlang感觉最好的方式是运行经常在彼此之间传递消息的小进程。建立一个庞大的列表并仔细研究它可能意味着要么Erlang是错误的选择,要么你的设计是糟糕的。(或者,作为最后手段,你需要扩展语言。)你的答案是有道理的。实际上,似乎不可能在erlang中创建未绑定的变量,因此,不使用reverse
就不可能创建问题的解决方案。也许,使用可以传递给其他进程的未绑定变量是个坏主意,因为同步这些值将非常困难。此外,由于erlang也不支持数据流变量,考虑到语言的限制,它使代码更易于阅读。谢谢你花时间回答。谢谢你的回答。在Oz中,变量也是单赋值的,但是,当创建变量时,它们没有默认值(即,变量是无限创建的)。当您执行此代码R=X | Unbound
时,意味着R
绑定到一对X
和Unbound
。您的代码似乎是正确的,但这正是我试图避免的。这是关键点:Erlang中根本不允许使用未绑定变量。我对Oz知之甚少,我保留的是您可以创建一个未绑定的变量,当需要此变量时,线程将“暂停”。然后另一个线程可以分配Var的值,前一个线程将继续。但要点是,如果在erlnag模块中保留一个未绑定的变量,erlc将不会编译代码。
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)].