是否能够声明Lisp函数';纯';有益吗?
我最近读了很多关于函数式语言的文章,以及它作为一种纯函数式语言所带来的好处。(我对讨论Lisp的monad不感兴趣)尽可能(至少在逻辑上)隔离具有副作用的函数对我来说是有意义的。我已经使用了大量的是否能够声明Lisp函数';纯';有益吗?,lisp,computer-science,compiler-optimization,proof,purely-functional,Lisp,Computer Science,Compiler Optimization,Proof,Purely Functional,我最近读了很多关于函数式语言的文章,以及它作为一种纯函数式语言所带来的好处。(我对讨论Lisp的monad不感兴趣)尽可能(至少在逻辑上)隔离具有副作用的函数对我来说是有意义的。我已经使用了大量的setf和其他破坏性函数,并且我认识到在Lisp及其(大多数)派生语言中需要它们 我们开始: 像(declare pure)这样的东西是否有助于优化编译器?或者这是一个没有实际意义的观点,因为它已经知道了 声明是否有助于证明函数或程序,或者至少证明声明为纯的子集?或者这又是一件不必要的事情,因为程序员、
setf
和其他破坏性函数,并且我认识到在Lisp及其(大多数)派生语言中需要它们
我们开始:
(declare pure)
这样的东西是否有助于优化编译器?或者这是一个没有实际意义的观点,因为它已经知道了为了澄清,我不打算把这个问题限制在CommonLisp上。它显然(我认为)不适用于某些派生语言,但我也很好奇其他Lisp的某些功能是否倾向于支持(或不支持)这种功能。给定一个Lisp函数,知道它是纯函数还是非纯函数通常是不可判定的。当然,必要条件和充分条件可以在编译时测试。(如果根本没有不纯操作,则函数必须是纯的;如果无条件执行不纯操作,则函数必须是不纯的;对于更复杂的情况,编译器可以尝试证明函数是纯的或不纯的,但它不会在所有情况下都成功。)
当我们可以假定纯粹性和参考性时,通常的好处适用 透明度。我们可以自动记忆热点。我们可以 自动并行计算。我们可以处理很多问题 竞争条件。我们也可以使用结构共享来共享我们需要的数据 know不能修改,例如(准)原语`cons() 不需要复制它考虑的列表中的cons单元格。 这些细胞不会受到另一个cons细胞的任何影响 这个例子有点明显,但编译器通常 在解决更复杂的结构共享方面表现出色 然而,实际确定lambda(函数)是纯的还是有 引用透明性在Common Lisp中非常棘手。记住这一点 funcall(foo-bar)从查看(符号函数foo)开始 这个案子
(defun foo (bar)
(cons 'zot bar))
foo()是纯的
下一个lambda也是纯的
(defun quux ()
(mapcar #'foo '(zong ding flop)))
但是,稍后我们可以重新定义foo:
(let ((accu -1))
(defun foo (bar)
(incf accu)))
对quux()的下一个调用不再是纯的!旧的纯foo()已被删除
重新定义为一个不纯的lambda.Yikes。这个例子可能有点
人为的,但从词汇上重新定义一些并不罕见
函数,例如一个let块。在这种情况下,它不是
可能知道编译时会发生什么
Common Lisp具有非常动态的语义,因此
能够提前确定控制流和数据流(例如
编译时的实例)非常困难,而且在大多数情况下都非常有用
完全不可判定。这是具有动态
在Lisp中有很多你不能使用的常用习惯用法
如果你必须使用静态输入法,那么主要是这些输入法会影响你的输入
尝试做很多有意义的静态分析。我们可以为原语做
像犯人和朋友,但对于兰巴斯来说,除了
原始人我们身处更深的水域,尤其是在
我们需要看看函数之间复杂的相互作用,记住这一点
只有当它调用的所有lambda都是纯的时,lambda才是纯的
(defun quux ()
(mapcar #'foo '(zong ding flop)))
在我的头顶上,有可能,通过一些深入的宏观研究,
从某种意义上说,每个lambda
一个额外的参数,它是一个表示整个状态的单子
lisp图像(我们显然可以限制自己使用什么函数
但能做到这一点可能更有用
声明我们自己的纯洁性,从我们向编译器承诺的意义上说
这个lambda确实是纯洁的,如果不是,后果就是
没有定义,各种混乱可能接踵而至……你有两个答案,但都没有触及真正的问题 首先,是的,知道一个函数是纯函数显然是好的