Макрос и пересечение массива - PullRequest
0 голосов
/ 16 января 2011

У меня проблема с макросом LISP. Я хотел бы создать макрос которые генерируют регистр переключения в соответствии с массивом.

Вот код для генерации коммутатора:

(defun split-elem(val)
  `(,(car val) ',(cdr val)))

(defmacro generate-switch-case (var opts)
  `(case ,var
     ,(mapcar #'split-elem opts)))

Я могу использовать его с таким кодом:

(generate-switch-case onevar ((a . A) (b . B)))

Но когда я пытаюсь сделать что-то вроде этого:

(defparameter *operators* '((+ . OPERATOR-PLUS)
                            (- . OPERATOR-MINUS)
                            (/ . OPERATOR-DIVIDE)
                            (= . OPERATOR-EQUAL)
                            (* . OPERATOR-MULT)))

(defmacro tokenize (data ops)
  (let ((sym (string->list data)))
    (mapcan (lambda (x) (generate-switch-case x ops)) sym)))

(tokenize data *operators*)

Я получил эту ошибку: *** - MAPCAR: A proper list must not end with OPS, но я не понимаю, почему.

Когда я печатаю тип ops, я получаю SYMBOL Я ожидал CONS, это связано?

Кроме того, для моей функции tokenize сколько раз оценивается лямбда (или макрос расширяется)?

Спасибо.

1 Ответ

1 голос
/ 17 января 2011

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

То, что вы хотите, похоже на это:

(defun tokenize (data ops)
    (mapcar (lambda (d)
               (cdr (assoc d ops)))
            (string->list data)))

CASE - это макрос, который ожидает несколько фиксированных предложений. Он не принимает предложения, которые вычисляются во время выполнения. Если данные списка должны стимулировать вычисления, используйте такие функции, как ASSOC.

GENERATE-SWITCH-CASE также является нечетным именем, поскольку макрос является регистром переключения.

GENERATE-SWITCH-CASE также ожидает список в качестве второго аргумента. Но в TOKENIZE вы называете это символом OPS. Помните, что макросы вычисляются с исходным кодом Lisp.

Далее, также не задействованы массивы. У Lisp есть массивы, но в вашем примере их нет.

Типичный совет:

  1. если вы хотите написать МАКРО, подумайте еще раз. Напишите это как функцию.

  2. , если вы все еще хотите написать макрос, перейдите к 1.

...