Оценка списка переменных в списке их значений в Common Lisp - PullRequest
2 голосов
/ 31 мая 2019

Мне интересно, как можно достичь следующего. Предположим, у меня есть список переменных, которые связаны некоторыми let выше. Я хотел бы превратить этот список в список значений, с которыми связаны эти переменные.

То есть предположим, что у нас есть

(define make-plist-from-variables (variables)
  (let ((keys variables)
        (values (mapcar #'identity variables)))
    (if (eq (length keys) (length values))
     (make-plist keys values)
     nil))))

Что я могу использовать вместо #'identity, чтобы правильно распаковать эти значения?

В данный момент следующий вызов производит следующий вывод.

CL-USER> (let ((a 2) (b 3)) (make-plist-from-variables '(a b)))
(A A B B)

Я бы хотел, чтобы это было (A 2 B 3)

Ответы [ 2 ]

5 голосов
/ 31 мая 2019

Это должен быть макрос, потому что нет способа извлечь лексическое значение переменной на основе ее символа.

(defmacro make-plist-from-variables (&rest variables)
  (loop :for binding :in variables
        :collect `',binding :into result
        :collect binding :into result
        :finally (return `(list ,@result))))

(macroexpand-1 '(make-plist-from-variables a b))
; ==> (list 'a a 'b b) 

(let ((a 2) (b 3)) 
  (make-plist-from-variables a b))
; ==> (a 2 b 3)

РЕДАКТИРОВАТЬ

Реализация без loop с использованием mapcan:

(defmacro make-plist-from-variables (&rest variables)
  `(list ,@(mapcan (lambda (v) `(',v ,v)) variables))
2 голосов
/ 31 мая 2019

Функции не имеют доступа к лексической среде своих вызывающих.Точнее, во время оценки вы не можете получить доступ к значениям лексических переменных, зная только их символы.Только макросы имеют доступ к объектам среды .

Специальным переменным

Вы можете использовать динамическое связывание:

(defun foo ()
  (declare (special a))
  (symbol-value 'a))

(let ((a 3))
  (declare (special a))
  (foo))

=> 3

В вашем случае вы должны собратьсимвол вдоль его значения, используя SYMBOL-vaLUE на всех ваших символах.

В связи с вашим вопросом, как динамически привязать переменные к значениям, для которых известны имена и / или значения переменныхво время оценки;см. специальный оператор PROGV.

Макросы

Вы можете получить, например, список ассоциаций, написав следующий код:

(acons 'a a (acons 'b b nil))

В зависимости отВ случае использования вашего вопроса вы можете захотеть иметь макрос, который расширяется до такого кода, который ссылается на переменные, которые вы хотите оценить.

...