2011-01-16 2 views
0

У меня проблема с макросом 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, сколько раз вычисляется лямбда (или макрос расширяется)?

Спасибо.

+0

Использование 'MACROEXPAND-1', чтобы увидеть, какой код генерирует макрос. – Svante

+0

Что вы пытаетесь сделать? Что такое 'data', и что вы хотите вернуть tokenize'? – Svante

+0

[13]> (macroexpand-1 '(generate-switch-case + ((+. "PLUS")))) (CASE + ((+' "PLUS"))); – Thomas

ответ

1

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

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

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

СЛУЧАЙ макрос, который ожидает кучу фиксированных положений. Он не принимает предложения, которые вычисляются во время выполнения. Если данные списка должны вычислять диск, то используйте такие функции, как ASSOC.

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

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

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

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

  1. , если вы хотите написать MACRO, подумайте еще раз. Напишите его как функцию.

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

+0

Спасибо за ваш ответ. Если бы я пытался написать макрос, он должен был тренироваться, потому что я только начал изучать lisp :) – Thomas

+1

@Thomas: есть несколько хороших представлений, объясняющих записи макросов в Common Lisp.Ознакомьтесь с практическим распространенным Lisp by Peter Seibel (бесплатный HTML онлайн) и на Lisp от Paul Graham (бесплатная версия PDF). Особенно последнее объясняет использование в деталях. –

+0

Я уже прочитал Землю из lisp, я нахожусь в Сейбеле :) Спасибо! (Следующим станет Пола Гархама) – Thomas

Смежные вопросы