1

Currently I'm using a fairly inefficient way to check if one list uses another list at it's end. Is there a more efficient way to do this?

(defun is-in-list (ls-haystack ls-ends-with)
  (catch 'found
    (while (not (or (eq ls-haystack t) (null ls-haystack)))
      (when (eq ls-haystack ls-ends-with)
        (throw 'found t))
      (setq ls-haystack (cdr ls-haystack)))))

2 Answers 2

5

What you are looking for is known in Common Lisp as tailp and is present in Emacs Lisp as cl-tailp:

(defun cl-tailp (sublist list)
  "Return true if SUBLIST is a tail of LIST."
  (while (and (consp list) (not (eq sublist list)))
    (setq list (cdr list)))
  (if (numberp sublist) (equal sublist list) (eq sublist list)))
0

Use nthcdr:

(let* ((x '(4 5))
       (y `(1 2 3 . ,x)))
  (eq (nthcdr (- (length y) (length x)) y)
      x))
;; => t
(defun foo (list list2)
  "Return t if LIST ends with LIST2."
  (eq (nthcdr (- (length list) (length list2)) list)
      list2))

(let ((x (list 4 5)))
  (foo (cons 1 (cons 2 x))
       x))
;; => t

;; it is ok if LIST is shorter than LIST2
(foo '(1 2) '(1 2 3 4))
;; => nil

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.