是否可以在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是个全新的人。作为学习该语言的练习,我尝试使用尾部递归实现函数
子列表
,而不使用
反向
。以下是我从该网站获得的功能:

在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)].