MikeB
MikeB

Reputation: 2452

Scheme syntax transformation

I am fairly new to Scheme, and I have been struggling with what I think should be a simple problem.

I am trying to convert something like

((qty 30) (name "ham")) to (sandwich "@qty" 30) (sandwich "@name" "ham")

Also, this must be dynamic to allow for extra clauses:

((qty 30) (name "ham") (cheese 'no))

Here is what I have so far:

(define-syntax (make-sandwiches x)
        (syntax-case x ()
            [(_ ((col val)...) ) #``(sandwich #,(format "@,~a" (caar #'((col val)...))) #,(cadar #'((col val)...)))] 
            [(_) "make-sandwiches is bad"]))

(make-sandwiches ((qty 30) (name "ham"))) => (param "@#(syntax qty)" 30)

So this is kinda close, but it only translates the first clause, so my idea is using map or something similar, but I'm not sure if that is correct either:

(define-syntax (make-sandwiches x)
        (syntax-case x ()
            [(_ ((col val)...)) (map (lambda (cv) #``(sandwich #,(format "@,~a" (caar cv)) #,(cadar cv))) #'((col val)...))] 
            [(_) "make-sandwiches is bad"]))

Upvotes: 2

Views: 102

Answers (1)

Óscar López
Óscar López

Reputation: 235984

Do you really have to use a macro? and return multiple values? a humble procedure that returns a list will do the trick:

(define (make-sandwiches lst)
  (map (lambda (data)
         (list 'sandwich
               (string-append "@" (symbol->string (car data)))
               (cadr data)))
       lst))

Or a bit shorter (you seem to be using Racket):

(define (make-sandwiches lst)
  (map (lambda (data) `(sandwich ,(format "@~a" (first data)) ,(second data)))
       lst))

For example, using the sample input in the question:

(make-sandwiches '((qty 30) (name "ham") (cheese 'no)))
=> '((sandwich "@qty" 30) (sandwich "@name" "ham") (sandwich "@cheese" 'no))

Upvotes: 4

Related Questions