函数式编程模型效率(特定于Erlang)

时间:2009-09-30 05:26:29

标签: functional-programming erlang

嗨,我是Erlang世界的新手。当我想到我们需要如何解决以下问题时(并且有一长串类似的问题),我认为它真的效率很低,因为我们说的是很多递归。显然,像C / Java这样的语言不需要笨拙的递归来解决这个问题,但是对于Erlang(我猜其他函数式编程语言也需要,也许?)你必须这样做。


示例3 - 附加

该程序连接两个列表:

append([], List) -> List;

append([First|Rest], List) -> [First | append(Rest,List)].

任何人都可以解释为什么这不是问题吗?

5 个答案:

答案 0 :(得分:12)

首先,阅读递归的Erlang efficiency guide

至于笨拙,不要忘记Erlang列表是单链表,所以你只有一个指向列表头部的“指针”,需要通过遍历列表来访问元素。 这将需要相同的数量,但不同类型的笨拙与所有指针或参考杂耍的语言。

至于效率,您可以以尾递归的方式实现它。尾递归被优化(see this SO question),使得编译的代码变得类似于你在C ++中实现的那样,唯一的区别是代替指针跳转,堆栈指针是倒带等等。

无论如何,尝试在Java和C ++中实现完全相同的功能,然后我们将看到哪一个更笨拙且更具可读性。

答案 1 :(得分:6)

  

嗨,我是C世界的新手。当我想到我们需要如何解决以下问题时(并且有一长串类似的问题),我认为这是非常低效的,因为我们说的是很多循环。显然,像Erlang这样的语言不需要笨拙的循环来解决这个问题,但是使用C(我猜其他程序编程语言也需要,也许?)你必须这样做。

看看我在那里做了什么? ;)

正如其他人所说,递归是一种完全正常(和有效)的方式来解决许多语言的问题。没有直接相关,但是......对于某些事情来说,递归比循环更容易理解(反过来也是如此)...... fib(n)。

答案 2 :(得分:4)

那么,为什么你认为递归效率低下?

在Erlang的情况下,它使用尾递归(.Net IL也可以这样做),实际上在处理方面效率稍高。

例如,使用尾递归,CPU会执行以下操作:

var first_list, second_list

label START_ITER:
  if(first_list is empty)
    goto FINISH

  var first_elem = first_list[0]
  var first_list.start_element = first_list[1]

  second_list[n+1] first_elem
  goto START_ITER

label FINISH:
  return second_list

对于for循环,你得到这样的东西:

var first_list, second_list

var i = 0
var limit = first_list.length

label START_ITER:
  if(i == limit)
    goto FINISH

  second_list[n+i+1] = first_list[i]
  i += 1
  goto START_ITER

label FINISH:
  // Done

尾部递归示例需要注意的是,列表拆分只会更改first_list指向的列表中的节点。 for循环示例使用更多变量赋值来做同样的事情。

这也说明了尾递归(只是一个goto)和正常递归之间差异的重要一点,它实际上会将一个函数加载到堆栈上。这种情况不会发生在尾递归和一般的erlang中。

这是一个近距离调用,但在for循环中有一些额外的检查和添加,所以我不能在效率方面推荐一个,但它的风格,递归条款完美地完成了。

我认为最好把它作为“迭代是人,回归,神圣”

答案 3 :(得分:0)

尾递归在每种函数语言中都得到了优化 - 与过程语言的循环(或者,ahem,goto ;-)相比,它没有任何开销。虽然您提供的具体示例可能是也可能不是“尾递归”,具体取决于语言(懒惰与急切的函数语言,例如),当您使用一种特定语言进行编码时,通常可以重构为纯尾递归表达式......如果需要的话。

用惰性语言,例如Haskell,append(Haskell相当于)[First | append(Rest, List)]将被保存为“thunk”,以便在需要时执行,而不是立即急切扩展。然后,当稍后某个模式匹配thunk与头/尾结构时 - 然后,只有这样,thunk才会被执行。

渴望(非懒惰)的语言有不同的方法,但效率并不低(尽管懒惰语言的粉丝可能认为它不那么优雅; - )。

答案 4 :(得分:0)

您可能不知道“erlc -S”和“to_core”选项,它们允许您检查字节码(BEAM或HiPE)

pattern matching - implementation

http://www.nabble.com/Re%3A-Idiomatic-Erlang%2C-style-performance-question-p18061921.html

HTH