1
votes

I need to write the lisp macro in scheme (please on hygienic macros and syntax-rules etc) that will have function call and Alist as argument

I want function and macro that call that function to have syntax like this:

(foo '(10 (a (lambda () (display "10")) b (lambda () (display "20"))))

or macro without quotes.

My last code is working, but not sure if this is how you suppose to write function/macro like this. It seems that I need double backquote but don't know how to write it. (I'm right now reading On Lips by Paul Graham and he said that double backquote is very hard and only need by macros defining macros, but It seems that this is what I need).

(define (foo expr)
    `(list ,(car expr)
           (,(string->symbol "quasiquote") ,(pair-map (lambda (a b)
                                                        (cons (symbol->string a)
                                                              (list 'unquote b)))
                                                      (cadr expr)))))

(define-macro (bar expr)
   (foo expr))

(define xx (bar (10 (a 20 b (lambda () (display "x") (newline))))))
;; (list 10 `((a . ,20) (b . ,(lambda () (display "x") (newline))))
(define bfn (cdr (assoc "b" (cadr xx)))))
(bfn)
;; "x"

and here is definition of pair-map

(define (pair-map fn seq-list)
  "(seq-map fn list)

   Function call fn argument for pairs in a list and return combined list with
   values returned from function fn. It work like the map but take two items from list"
  (let iter ((seq-list seq-list) (result '()))
    (if (null? seq-list)
        result
        (if (and (pair? seq-list) (pair? (cdr seq-list)))
            (let* ((first (car seq-list))
                   (second (cadr seq-list))
                   (value (fn first second)))
              (if (null? value)
                  (iter (cddr seq-list) result)
                  (iter (cddr seq-list) (cons value result))))))))

with (string->symbol "quasiquote") I was able not to use double backquote, can this be written with double backquote/quasiquote? How this should look like?

I'm asking if this can be written different way so I can fix few issues in my own lisp interpreter (not sure if is working correctly but it seems that this final version works the same in guile).

1
map-pair has a one armed if. Thus pair-map might return "BaNaNa" since the behaviour of one armed if is underspecified. What is the code (bar (10 (a 20 b (lambda () (display "x") (newline))))) suppose to expand to?Sylwester
@Sylwester it suppose to be list with car and Alist as second item, it should expand into (list 10 ((a . 20) (b . (lambda () (display "x") (newline)))jcubic
I think I understand. You mean it expands to (list 10 `((a . ,20) (b . ,(lambda () (display "x") (newline))) so that the lambda becomes a function?Sylwester
@Sylwester yes, I've edited the question.jcubic
I'm not sure if I understand the question, but if you want to make alist of procedures, you can simply use quasiquote instead of using a macro.Takashi Kato

1 Answers

0
votes

I came up with shorter quasiquote version, but still it require inserting symbols:

(define (foo expr)
    `(list ,(car expr)
           (,'quasiquote ,(pair-map (lambda (a b)
                                      `(,(symbol->string a) . (,'unquote ,b)))
                                    (cadr expr)))))