考虑这个示例函数:
第一个示例
;;; Lisp
(defun foo (x y z)
(let ((tmp))
(setf tmp (operation1 x y z))
(setf tmp (operation2 tmp y z))
(setf tmp (operation3 tmp y z))
(setf tmp (operation4 tmp y z))
...
(setf tmp (operationN tmp y z))
tmp))
// PHP
function foo($x, $y, $z)
{
$tmp = operation1($x, $y, $z);
$tmp = operation2($tmp, $y, $z);
$tmp = operation3($tmp, $y, $z);
...
return operationN($tmp, $y, $z);
}
我的老师告诉我,在函数式编程中,我不应该在temp变量中存储返回值,而是立即将它传递给下一个函数。
第二个例子
;;; Lisp
(defun foo (x)
(operationN
(...
(operation3
(operation2
(operation1 x y z)
y z)
y z)
y z)
y z)
)
// PHP
function foo($x, $y, $z)
{
return operationN(
...(
operation3(
operation2(
operation1($x, $y, $z),
$y, $z),
$y, $z),
$y, $z),
$y, $z);
}
将此视为一个非常简单的示例,并且可能还有其他函数应用于其余参数。在我看来,第一个例子更具可读性。
答案 0 :(得分:3)
代码变得笨拙往往表明单一职能的责任太大 在我看来,两种语言中的“正确”方式是重构为较小的函数。
这种重构当然取决于实际问题,但是你的例子的细分可能是
(defun operations1-2 (x y z)
(operation2 (operation1 x y z) y z))
(defun operations1-3 (x y z)
(operation3 (operations1-2 x y z) y z))
(defun operations1-4 (x y z)
(operation4 (operations1-3 x y z) y z))
...
(defun foo (x y z)
(operationN (operations1-N-1 x y z) y z))
当然,你不能总是以有意义的方式做到这一点,但也有顺序的let-binding,这比深层嵌套的函数应用程序更好:
(defun foo (x y z)
(let*
((tmp (operation1 x y z))
(tmp2 (operation2 tmp y z))
(tmp3 (operation3 tmp2 y z))
(tmp4 (operation4 tmp3 y z))
(...))
(operationN tmpN-1 y z)))