Как использовать функцию в качестве переменной в LISP?

Я пытаюсь написать функцию, которая проверяет, есть ли у каждого элемента в списке x свойство a, поэтому я написал:

(defun check (a x)
  (if (listp x)
    (eval (cons 'and (mapcar #'a x)))))

но это не работает (В основном я хочу a быть названием функции, скажем blablablaи в теле функции проверки, #'a Я хочу иметь в виду функцию blablablaвместо функции с именем a.) Теперь приведенный выше код не работает. Я думаю, что в Лиспе нужно иметь возможность подключать функции. Как я могу это исправить?

(Это буквально мой первый день на lisp, так что это может быть глупый вопрос;) И кстати, я использую личную версию Lispworks 6.0.)

3 ответа

Решение

Здесь нет необходимости использовать синтаксис с точными кавычками. Его целью является использование имени функции в переменной позиции, но a переменная уже Просто пиши a вместо #'a,

Вам не нужно eval ты можешь использовать apply, К проблеме: вам нужно funcall потому что вы предоставляете a в качестве аргумента. (Правка: не в этом случае.) Цитируя, вы просто ссылаетесь на функцию a не в этой функции.

(defun check (a xs)
  (if (listp xs)
      (every #'identity (mapcar a
                                xs))))

Лучше использовать loop:

(defun check (a xs)
  (if (listp xs)
      (loop for x in xs
            always (funcall a x))))

Лучше всего использовать every:

(defun check (a xs)
   (if (listp xs)
     (every a xs)))

Вот как я бы написал что-то вроде вашей функции проверки. Я попытался дать ему более описательное имя.

(defun are-all-elements-fullfilling-fun-p (fun ls)
  (every #'identity (mapcar fun ls)))

Изменить: обратите внимание, что более короткое и лучшее определение

(defun are-all-elements-fullfilling-fun-p (fun ls)
      (every fun ls)))

Теперь допустим, что мы хотим вызвать его с помощью этой функции. Обратите внимание, что я склонен использовать объявления, когда это возможно. Я довольно часто что-то путаю, и отладка очень проста, если компилятор может понять ошибку. Также код будет работать быстрее.

(defun is-even-p (n)
  (declare (type number n))
  (the boolean (= 0 (mod n 2))))

Вы должны поместить # здесь:

(are-all-elements-fullfilling-fun-p #'is-even-p '(1 2 3 4))
(are-all-elements-fullfilling-fun-p #'is-even-p '(38 2 4))
Другие вопросы по тегам