functional-programming - LISP 从函数返回值的适当方式
问题描述
因此,我正在研究 Paul Graham 的 Common Lisp 并且有一个问题要求创建一个联合函数,该函数保持被联合化的列表中元素的顺序。为此,我编写了以下函数:
(defun new-union (listA listB)
(setq retset (list (car listA)))
(loop for el in (append (cdr listA) listB)
do (if (not(member el retset))
(push el (cdr (last retset)))))
(return-from new-union retset))
这将返回每个列表的唯一元素,同时保持顺序,因此如果我创建并运行:
(setq listA '(a b c a))
(setq listB '(c d e))
(new-union listA listB)
回报是:
(A B C D E)
所以第一件事是我得到一个编译器警告:"undefined variable: RETSET"
在这一行:(setq retset (list (car listA)))
。另一件事是,上面的方法似乎是一种更“面向对象”的做事方式,而不是带有return-from
语句的LISP方式。
是否可以在没有编译器错误的情况下以更“适合lisp”的方式编写此代码?
*编辑:使用@Sylwester的答案,我重写了如下函数并且没有错误:
(defun new-union (listA listB)
(let ((retset (list (car listA))))
(loop for el in (append (cdr listA) listB)
do (if (not (member el retset))
(push el (cdr (last retset)))))
retset))
解决方案
setq
是更新一个现有的绑定并且你的变量retset
没有被创建。标准中未指定如何处理此问题,因此您不能依赖涉及它的代码。defparameter
您可以使用和defvar
创建全局变量,而您可以使用&aux
in 函数创建局部变量,let
并且loop
可以使用with
. 因此:
(defun new-union (list-a list-b)
(let ((retset (list (car list-a))))
...
retset
))
与使用&aux相同:
(defun new-union (list-a list-b &aux (retset (list (car list-a))))
...
retset
)
也与带有子句的循环相同:
(defun new-union (list-a list-b)
(loop :with retset := (list (car list-a))
...
:finally (return retset)))
关于返回值。在尾部位置,评估的值是返回值。例如。
(if (< 3 4)
8
10)
这里8
返回。这意味着(return from new-union retset)
在您的代码中,位于尾部位置的代码可能只写retset
.
现在,如果您有不在尾部位置的代码并且您希望早点返回,您可以执行您在尾部位置所做的事情,它会起作用。
我使用(return retset)
的那个从最近的未命名 ( nil
) 块return-from
返回,而从命名块返回。具有允许您选择它产生的块的名称loop
的关键字。named
让 lisper 实现这样一个微不足道的功能,你会得到很多答案。有了你的规格和测试,我会做的:
(defun new-union (&rest lists &aux (hash (make-hash-table :test 'equal)))
(loop :for list :in lists
:nconc (loop :for element :in list
:if (gethash element hash t)
:collect element
:do (setf (gethash element hash) nil))))
推荐阅读
- angular - 需要帮助使用此 API 来显示信息 (Ionic 3)
- r - 如何使用 mutate 函数用索引号替换唯一值?
- msbuild - 找不到 signtool 的临时位置。退出
- python - Pyspark - 使用广播字典中的日期过滤 RDD
- java - 动态 TextView 未在片段中更新
- azure - Azure 多个部署 409 冲突
- html - 当我保存时,内联 css 在文本编辑器中被删除。它创建了一个丑陋的 html 按钮,无处可去
- ios - 如何正确补偿CGContextRef坐标系,使原点在左上角
- chromecast - Chromecast Ultra 会限制 HTML 分辨率吗?
- python - 使用 Python 在 Glade 中显示我在 frame1 上录制的图像文件在 frame2 上显示