所以我想比較來自四個不同列表的四個不同元素。就像下面這個例子一樣,問題是平等應該只能接收2個參數,是否有任何函數可以比較2個以上的元素?比較多個元素
(equal (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 3)))
所以我想比較來自四個不同列表的四個不同元素。就像下面這個例子一樣,問題是平等應該只能接收2個參數,是否有任何函數可以比較2個以上的元素?比較多個元素
(equal (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 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)))
or'(defun equal *(&rest arguments)(every#'equal arguments(rest arguments)))''。 – Svante 2014-12-08 09:53:42
@Svante哦,這很好,並以不同的方式利用了等式謂詞的傳遞性。太好了! – 2014-12-08 17:45:38
例如你可以用第一個,類似的東西,每一個元素比較:
(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
在一般情況下這不是一個錯誤的選項,而且它是實現n元比較/等式謂詞的簡單方法。然而,在OP的情況下,它的數字是被比較的,'='操作符可能會工作,並且已經是n-ary了。 – 2014-12-05 16:49:36
如果你只是比較數字,你可以使用接受任意數量參數的'='。 – 2014-12-05 16:46:48