函数式编程是如何在底层实现的?
How is functional programming implemented in low level?
Haskell、Scala、...和函数式编程语言一般是如何在底层实现的?也就是说,如果是冯·诺依曼,计算机实际上如何 运行 一个功能程序?代码是怎么翻译的(一般是解释型,不知道有没有编译型函数式语言)?
简答:
通过将功能转换为动作序列(某些虚拟机或真实机器中的指令)。
更长的答案:
考虑这个函数式程序,使用 Lisp 符号来使我们摆脱句法困难:
;; function definitions
(defun square (x) (* x x))
(defun difference (a b)
(if (> a b)
(- a b)
(- b a)))
;; actual program
(difference (square 5) 5)
假设严格(不是惰性)评估,在计算 difference
之前,您显然需要计算 square
。概括这个想法意味着为了计算一个函数,你首先需要计算它的参数。计算参数的顺序可能未指定,但为了简单起见,我们假设它们是从左到右计算的。然后,您可以将上面的程序(省略函数定义)转换为以下命令式描述:
1: use value 5 as parameter
2: call square using 1 parameter, use result as parameter
3: use value 5 as parameter
4: call difference using 2 parameters
例如,对于基于堆栈的机器,可以相对容易地编译此操作序列:
square:
dup ; duplicate top of stack
mul ; pops 2 numbers from stack, multiplies them and pushes the result
ret
difference:
compare_greater_than ; uses the top 2 numbers from stack, pushes result
jmpif L ; pops 1 number from stack, jumps if non zero
swap ; swap top 2 numbers on stack
L: sub
ret
main:
push 5
call square
push 5
call difference
当然,这只是一个非常粗略的草图,但希望能让您了解从哪里开始。我在这里的其他两个答案中实施了 as well as a more 。两者都是解释函数式程序的示例。
然后,还有关于如何实际实现函数式语言的很好的教程,例如 http://www.buildyourownlisp.com/。
我的回答完全集中在 "practical" 方法上。还有很多我完全遗漏的理论,比如 spineless tagless G-machine、向连续传递样式的转换或一些严肃的图表内容,但我希望我的回答能让你知道从哪里开始。
你犯了逻辑谬误,当你问:
That is, how a computer can actually run a functional program if it's Von Neumann?
但是我们的计算机可以计算任何可以计算的东西,无论硬件架构如何。这就好像你在问:当计算机由电子元素组成时,它如何帮助化学。
Haskell、Scala、...和函数式编程语言一般是如何在底层实现的?也就是说,如果是冯·诺依曼,计算机实际上如何 运行 一个功能程序?代码是怎么翻译的(一般是解释型,不知道有没有编译型函数式语言)?
简答:
通过将功能转换为动作序列(某些虚拟机或真实机器中的指令)。
更长的答案:
考虑这个函数式程序,使用 Lisp 符号来使我们摆脱句法困难:
;; function definitions
(defun square (x) (* x x))
(defun difference (a b)
(if (> a b)
(- a b)
(- b a)))
;; actual program
(difference (square 5) 5)
假设严格(不是惰性)评估,在计算 difference
之前,您显然需要计算 square
。概括这个想法意味着为了计算一个函数,你首先需要计算它的参数。计算参数的顺序可能未指定,但为了简单起见,我们假设它们是从左到右计算的。然后,您可以将上面的程序(省略函数定义)转换为以下命令式描述:
1: use value 5 as parameter
2: call square using 1 parameter, use result as parameter
3: use value 5 as parameter
4: call difference using 2 parameters
例如,对于基于堆栈的机器,可以相对容易地编译此操作序列:
square:
dup ; duplicate top of stack
mul ; pops 2 numbers from stack, multiplies them and pushes the result
ret
difference:
compare_greater_than ; uses the top 2 numbers from stack, pushes result
jmpif L ; pops 1 number from stack, jumps if non zero
swap ; swap top 2 numbers on stack
L: sub
ret
main:
push 5
call square
push 5
call difference
当然,这只是一个非常粗略的草图,但希望能让您了解从哪里开始。我在这里的其他两个答案中实施了
然后,还有关于如何实际实现函数式语言的很好的教程,例如 http://www.buildyourownlisp.com/。
我的回答完全集中在 "practical" 方法上。还有很多我完全遗漏的理论,比如 spineless tagless G-machine、向连续传递样式的转换或一些严肃的图表内容,但我希望我的回答能让你知道从哪里开始。
你犯了逻辑谬误,当你问:
That is, how a computer can actually run a functional program if it's Von Neumann?
但是我们的计算机可以计算任何可以计算的东西,无论硬件架构如何。这就好像你在问:当计算机由电子元素组成时,它如何帮助化学。