2014-12-05 123 views
3

所以我想比较来自四个不同列表的四个不同元素。就像下面这个例子一样,问题是平等应该只能接收2个参数,是否有任何函数可以比较2个以上的元素?比较多个元素

(equal (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 3))) 
+0

如果你只是比较数字,你可以使用接受任意数量参数的'='。 – 2014-12-05 16:46:48

回答

3

没有任何功能比较多2个元素?

Common Lisp中的许多比较函数接受两个以上的参数。例如,所有的=, /=, <, >, <=, >=接受任何数量的参数,这意味着你可以做

(= (nth 0 '(1 2 3)) 
    (nth 0 '(1 2 3)) 
    (nth 0 '(1 2 3)) 
    (nth 0 '(1 2 3))) 

如果你需要的等于(而不是=)的具体行为,那么你会想办法那coredump proposed。因为平等是传递的,你可以检查每一个元素是等于的第一个元素(或者列表为空):

(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))) 
+1

or'(defun equal *(&rest arguments)(every#'equal arguments(rest arguments)))''。 – Svante 2014-12-08 09:53:42

+0

@Svante哦,这很好,并以不同的方式利用了等式谓词的传递性。太好了! – 2014-12-08 17:45:38

4

例如你可以用第一个,类似的东西,每一个元素比较:

(defun meql (func &rest args) 
    (every (lambda (arg) 
      (funcall func arg (first args))) 
     (rest args))) 

CL-USER> (meql #'eq 'a 'a 'a) 
T 
CL-USER> (meql #'eq 'a 'b 'a) 
NIL 
CL-USER> (meql #'equal "foo" "FOO" "foo") 
NIL 
CL-USER> (meql #'equalp "foo" "FOO" "foo") 
T 
+1

在一般情况下这不是一个错误的选项,而且它是实现n元比较/等式谓词的简单方法。然而,在OP的情况下,它的数字是被比较的,'='操作符可能会工作,并且已经是n-ary了。 – 2014-12-05 16:49:36