Как мне проверить, есть ли уже строка в списке в Emacs Lisp? Мне нужно проверить, есть ли уже определенная строка пути в exec-path, а затем добавить ее в этот список, если это не так.

15
λ Jonas Gorauskas 22 Май 2009 в 10:25

2 ответа

Лучший ответ

Функция add-to-list проверит автоматически перед добавлением

(setq a '(1 2 3))
(add-to-list 'a 4)
(add-to-list 'a 3)

Приведет к a, равному (4 1 2 3)

Из Emacs 26 C-h f add-to-list:

(add-to-list LIST-VAR ELEMENT &optional APPEND COMPARE-FN)

Add ELEMENT to the value of LIST-VAR if it isn’t there yet.
The test for presence of ELEMENT is done with ‘equal’, or with
COMPARE-FN if that’s non-nil.
If ELEMENT is added, it is added at the beginning of the list,
unless the optional argument APPEND is non-nil, in which case
ELEMENT is added at the end.

The return value is the new value of LIST-VAR.

This is handy to add some elements to configuration variables,
but please do not abuse it in Elisp code, where you are usually
better off using ‘push’ or ‘cl-pushnew’.

If you want to use ‘add-to-list’ on a variable that is not
defined until a certain package is loaded, you should put the
call to ‘add-to-list’ into a hook function that will be run only
after loading the package.  ‘eval-after-load’ provides one way to
do this.  In some cases other hooks, such as major mode hooks,
can do the job.
25
chwarr 22 Май 2020 в 09:31

В дополнение к cobbal's ответ о add-to-list, есть также cl-pushnew:

(require 'cl-lib)

(setq list-of-strings '("one" "two" "three"))
(cl-pushnew "two" list-of-strings :test #'string=)
    ⇒ ("one" "two" "three")
(cl-pushnew "zero" list-of-strings :test #'string=)
    ⇒ ("zero" "one" "two" "three")

:test #'string= аргумент требуется в вашем случае, потому что cl-pushnew использует eql для сравнения по умолчанию, и он не рассматривает две строки с одинаковым содержанием как равные. ( equal ) тоже будет работать.

(eql "some-string" "some-string")
    ⇒ nil
(string= "some-string" "some-string")
    ⇒ t
(equal "some-string" "some-string")
    ⇒ t

Из Emacs 26 C-h f cl-pushnew:

cl-pushnew is a Lisp macro in ‘cl-lib.el’.

(cl-pushnew X PLACE [KEYWORD VALUE]...)

(cl-pushnew X PLACE): insert X at the head of the list if not already there.
Like (push X PLACE), except that the list is unmodified if X is ‘eql’ to
an element already on the list.

Keywords supported:  :test :test-not :key
2
Community 20 Июн 2020 в 12:12