Well, if you want to roll your own instead of using cl-position
, and you don't want to traverse twice (using length
)...
(defun nth-elt (element xs)
"Return zero-indexed position of ELEMENT in list XS, or nil if absent."
(let ((idx 0))
(catch 'nth-elt
(dolist (x xs)
(when (equal element x) (throw 'nth-elt idx))
(setq idx (1+ idx)))
nil)))
That's good for even old Emacs versions. However, it has this behavior difference, which you might or might not want: It works also for the cars of a dotted list. That is, it correctly returns the position instead of raising an error, for sexps such as (nth-elt 'c '(a b c . d))
.
If you want to always raise an error for an improper list, then you will want to check for that case, which requires always traversing to the end of the list:
(defun nth-elt (element xs)
"Return zero-indexed position of ELEMENT in list XS, or nil if absent."
(let ((idx 0))
(when (atom (cdr (last xs))) (error "Not a proper list"))
(catch 'nth-elt
(dolist (x xs)
(when (equal element x) (throw 'nth-elt idx))
(setq idx (1+ idx)))
nil)))