2017-10-29 103 views
0

假设我想从状态列表中删除一个步骤(元素)。多于一个参数用于删除谓词 - 如果

(defparameter *states* '((:top nil nil) (:subjects nil nil))) 
;predicate 
(defun equal-state? (step state) 
    (equal (car step) state)) 

如果我使用(delete-if #'equal-state? *states*)那么如何在第二个参数(state)可以传递给谓词?

编辑:我终于找到了一个类似的问题,但我倾向于保留它,因为问题的清晰。

+1

NB。在这个例子中,你正在使用DELETE,它有权改变数据,但你的数据是常量(引用列表),不应该在便携式程序中修改。 – coredump

回答

3
CL-USER 67 > (let ((state :top)) 
       (delete-if (lambda (step) 
          (equal-state? step state)) 
          *states*)) 
((:SUBJECTS NIL NIL)) 

CL-USER 68 > (defun make-predicate (state) 
       (lambda (step) 
       (equal-state? step state))) 
MAKE-PREDICATE 

CL-USER 69 > (delete-if (make-predicate :subjects) 
         *states*) 
((:TOP NIL NIL)) 

作为用户信息转储提到,delete-if是一个潜在的破坏性操作。 delete-if的非破坏性替代品是remove-if

你也可以使用remove/delete

CL-USER 77 > (remove :subjects 
        '((:top nil nil) 
         (:subjects nil nil)) 
        :key #'first 
        :test #'equal) 
((:TOP NIL NIL)) 
+0

@coredump暗示,不应该在便携式程序中修改常量数据......我的lisp实现也会警告我有关常量数据的问题..我无法将自己的头围绕在它上面......以及“便携式程序中的常量数据?” –

+1

@BilalQadri:如果你的程序中写有'(a b c)',它就是一个引用列表。这个列表是文字数据。没有指定如果你修改它会发生什么。可以工作,可能有副作用,可以默默地失败,可能会导致错误。未指定。一个新的清单将被创建,具有LIST,COPY-LIST等许多功能。如果您向REPL键入文字列表,您可以在不看到问题的情况下对其进行修改,但通常情况并非如此。特别是在编译代码中,它可能会导致问题。这不是Lisp特有的。其他朗也有类似的问题。 –