Tim*_*eld 14 lisp programming-languages functional-programming
作为函数式编程的新手,我耗费了大量的精力,想知道"这是做事的功能性方法吗?"显然,递归与迭代非常简单,很明显递归是功能性的做事方式.但是以闭包为例.我已经了解了使用Lisp的闭包,我理解闭包是一个函数和一个环境的组合(听起来很像状态和行为).例如:
(let ((x 1))
(defun doubleX()
(setf x (* x 2))))
Run Code Online (Sandbox Code Playgroud)
这里我们有一个函数doubleX,它已经在x变量的环境中定义.我们可以将此函数传递给其他函数,然后调用它,它仍然可以引用x变量.该函数可以继续引用该变量,即使它是在已定义变量的环境之外调用的.我看过闭包的许多例子都是这样的.其中setf用于更改词法变量的值.这让我很困惑,因为:
1.)我认为setf是邪恶的.主要是因为它会引起副作用,显然它们也是邪恶的.
2.)这真的"功能性"吗?似乎只是一种保持全球状态的方式,我认为功能语言是无状态的.
也许我只是不明白闭包.有人可以帮我吗?
Kyl*_*nin 12
你是对的,使用闭包来操纵状态并不是纯粹的功能.Lisp允许您以功能样式进行编程,但它不会强制您使用.我实际上更喜欢这种方法,因为它允许我在纯功能和修改状态的便利之间取得实际的平衡.
您可能尝试的是从外部编写看似有用的东西,但保持内部可变状态以提高效率.一个很好的例子就是memoization,你可以记录所有以前的调用来加速像fibonacci这样的函数,但是因为函数总是为同一个输入返回相同的输出并且不修改任何外部状态,所以可以考虑从外面发挥作用.
闭包是一个穷人的对象(反之亦然),请参阅
我的回答.因此,如果您打算在非OO应用程序中使用副作用来管理状态,那么关闭over-mutable-state确实是一种简单的方法.不可改变的替代品"不那么邪恶",但99.9%的语言提供可变状态,并且它们不可能都是错误的.:)明智地使用可变状态是有价值的,但是当与闭包和捕获一起使用时,它可能特别容易出错,如此处所示
在任何情况下,我认为你看到"这么多这样的例子"的原因是解释闭包行为的最常见方法之一就是展示一个像这样的小例子,其中一个闭包捕获一个变量,从而成为一个迷你-stateful-object,封装了一些可变状态.这是一个很好的例子,可以帮助确保您了解构造的生命周期和副作用影响,但并不认可在整个地方使用此构造.
大部分时间关闭,你只需关闭值或不可变状态,并且"不注意"你正在做它.