2014-12-05 111 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