Reputation: 2452
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
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