因此,我想比较来自四个不同列表的四个不同元素。像下面这样的例子,问题是等于应该只接受2个参数,是否有任何函数可以比较2个以上的元素?
(equal (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 3)))
有什么功能可以比较两个以上的元素?
Common Lisp中的许多比较函数都接受两个以上的参数。例如,所有=,/ =,<,>,<=,> =均可接受任意数量的参数,这意味着您可以执行
(= (nth 0 '(1 2 3))
(nth 0 '(1 2 3))
(nth 0 '(1 2 3))
(nth 0 '(1 2 3)))
如果您需要equal(而不是=)的特定行为,那么您将需要coredump提出的方法。由于相等性是可传递的,因此您可以检查每个元素是否等于第一个元素(或列表为空):
(defun equal* (&rest arguments)
(or (endp arguments)
(let ((x (first arguments)))
(every (lambda (y)
(equal x y))
(rest arguments)))))
(equal* 1 1 1 1)
;=> T
实际上,因为你可以调用第一和休息用的空列表,你甚至可以摆脱第一种情况,因为每一个在传递一个空列表将返回true:
(defun equal* (&rest arguments &aux (x (first arguments)))
(every (lambda (y)
(equal x y))
(rest arguments)))
之后,由于这可能是常见的模式,因此您可以定义一个宏来为您定义这些:
(defmacro def-n-ary-equality (name predicate &rest args)
(let ((arguments (gensym (string '#:arguments-)))
(x (gensym (string '#:x-)))
(y (gensym (string '#:y-))))
`(defun ,name (&rest ,arguments &aux (,x (first ,arguments)))
(every (lambda (y)
(,predicate ,x ,y ,@args))
(rest ,arguments)))))
(def-n-ary-equality equal* equal)
; ==
(DEFUN EQUAL* (&REST #:ARGUMENTS-1005 &AUX (#:X-1006 (FIRST #:ARGUMENTS-1005)))
(EVERY (LAMBDA (Y)
(EQUAL #:X-1006 #:Y-1007))
(REST #:ARGUMENTS-1005)))
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句