存在全新的“函数式编程”范式,与程序式编程相比,需要彻底改变思维模式。它使用更高阶函数,纯度,monad等,我们通常在命令式和面向对象语言中看不到它们。
我的问题是这些语言的实现与命令式或面向对象语言的区别,例如,内存管理或内部指针等。
有一些函数语言在JVM之上运行。这是否意味着这些语言在内部像JVM上的其他语言一样工作?
答案 0 :(得分:8)
由函数式语言生成的代码使用了您在非函数语言中不同程度地看到的许多功能。垃圾收集已经普遍使用。尾调优化是{{3}}。
然而,闭包是功能编程的标志。你没有看到一个没有另一个。如果你定义“函数式语言”只能引用纯函数式语言,那么这两者并不是同义的,因为你会发现支持函数式编程的命令式语言中的闭包(例如Javascript和Scheme(这在技术上是必要的,尽管功能范式是主要的)用过的))。可以使用done in GCC and VC++为调用堆栈实现闭包,或者在退出堆栈帧时复制局部变量,或者通过在堆上分配局部变量并让垃圾收集来处理它们。一旦你有闭包,匿名函数相对容易(使用解释器,它们真的很容易)。使用编译器,函数在编译时转换为字节码,字节码(而不是入口点的地址)在运行时与当前环境相关联。
函数组合可以依赖匿名函数。当编译器遇到函数组合运算符f . g
时,它会创建一个匿名函数,该函数调用两个参数f
和g
,将一个结果作为参数传递给另一个。
Monads可以用OO语言实现,它们不像纯函数式语言那样必要。 I / O monad并不是特别的,他们只是依赖于底层平台允许副作用的事实。
答案 1 :(得分:5)
功能编程语言的实现正在使用各种实现技术。对于Scheme(Lisp方言)的实现的一个很好的介绍给出了这本书:Lisp in Small Pieces由Christian Queinnec。
答案 2 :(得分:1)
我想在功能语言中有很多方面受益于特别关注,我想到的是:
功能语言经常使用递归。所以任何实现都应该尝试优化这种情况。例如。识别尾递归并在内部转换为循环(从而保存函数调用开销,如堆栈保存/恢复)。 (http://en.wikipedia.org/wiki/Tail_recursion)
答案 3 :(得分:1)
Haskell等函数式编程语言的实现通常与命令式语言的实现非常不同。您可以阅读有关实现此目的的一种方法here。尽管该论文已有几年历史,但我相信这些想法仍在使用。
答案 4 :(得分:1)
我们想到的最大区别是,函数式语言的设计倾向于使源代码desugared成为一种数学上简单而强大的中间语言。这种语言通常包含lambda,函数调用,if / else,机器类型,类似let
,而不是更多。转换后的代码是深度嵌套的,冗长的,并且不具有人类可读性。表面语法被丢弃。
像这样的语言的编译器必须进行一些内联和一些闭包优化来生成合适的代码。 (对我来说,这些基线闭包优化看起来非常重要 - 逃避分析等等 - 但可能只是缺乏熟悉性。)
答案 5 :(得分:0)
所有东西都在同一个处理器上运行(因此也是相同的汇编指令),所以只要你足够深入,内部的一切都是一样的。
答案 6 :(得分:0)
@outis:虽然语言可能支持它们,但闭包与函数的数学概念冲突的方式与副作用相同:它们允许您从相同的参数中获得不同的结果。这使得闭包是程序性的,而不是功能性的。
也就是说,有效率参数支持闭包而不是全局变量(特别是在编译器实现的上下文中)。 [但我知道直接提供闭包的函数式语言,即使可以实现“work alikes”。]
(但是,currying类似于闭包,并没有遭受这种冲突,并且确实存在于函数式语言中。)
无论如何,在我看来,函数式编程语言是一种语言,它们努力使计算可以表示为数学函数。这意味着优化功能倾向于优化。
假设至少,函数式语言允许机器在更深层次的抽象上工作,而不是纯粹的程序性方法。