Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare multiple elements

So I want to compare four different elements, from four different lists. Something like the example bellow, the problem is that equal should only recieve 2 arguments, is there any function to compare more than 2 elements?

(equal (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 3)) (nth 0 '(1 2 3)))
like image 588
sok Avatar asked Sep 02 '26 01:09

sok


1 Answers

is there any function to compare more than 2 elements?

Many of the comparison functions in Common Lisp accept more than two arguments. For instance, all of =, /=, <, >, <=, >= accept any number of arguments, which means that you can do

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

If you need the specific behavior of equal (and not =), then you'll want the approach that coredump proposed. Since equality is transitive, you can check that every element is equal to the first element (or that the list is empty):

(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

Actually, since you can call first and rest with the empty list, you could even get rid of the first case, since every will return true when passed the empty list:

(defun equal* (&rest arguments &aux (x (first arguments)))
  (every (lambda (y)
           (equal x y))
         (rest arguments)))

After that, since this might be a common pattern, you could define a macro to define these for you:

(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)))
like image 68
Joshua Taylor Avatar answered Sep 05 '26 01:09

Joshua Taylor