Thomas
Thomas

Reputation: 3

Macro and array crossing

I am having a problem with a lisp macro. I would like to create a macro which generate a switch case according to an array.

Here is the code to generate the switch-case:

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

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

I can use it with a code like this:

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

But when I try to do something like this:

(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*)

I got this error: *** - MAPCAR: A proper list must not end with OPS, but I don't understand why.

When I print the type of ops I get SYMBOL I was expecting CONS, is it related?

Also, for my function tokenize, how many times is the lambda evaluated (or the macro expanded)?

Thanks.

Upvotes: 0

Views: 560

Answers (1)

Rainer Joswig
Rainer Joswig

Reputation: 139311

This makes no sense. You trying to use macros, where functions are sufficient.

What you want is similar to this:

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

CASE is a macro that expects a bunch of fixed clauses. It does not take clauses that are computed at runtime. If list data should drive computation, then use functions like ASSOC.

GENERATE-SWITCH-CASE is also an odd name, since the macro IS a switch case.

GENERATE-SWITCH-CASE also does expect a list as a second argument. But in TOKENIZE you call it with a symbol OPS. Remember, macros compute with Lisp source code.

Next, there are also no ARRAYs involved. Lisp has arrays, but in your example is none.

Typical advice:

  1. if you want to write a MACRO, think again. Write it as a function.

  2. if you still want to write a macro, Go to 1.

Upvotes: 1

Related Questions