Reputation: 22460
I am learning scheme/racket macros, and trying to make the following macro from sweet-macros work under racket 8.6.
#lang racket
(require (for-meta 1 srfi/1)) ; for cons* and fold-right
(provide guarded-syntax-case)
;;GUARDED-SYNTAX-CASE
(define-syntax guarded-syntax-case
(let ((add-clause
(lambda (clause acc)
(syntax-case clause ()
((pattern skeleton . rest)
(syntax-case #'rest ()
((cond? else1 else2 ...)
(cons*
#'(pattern cond? skeleton)
#'(pattern (begin else1 else2 ...))
acc))
((cond?)
(cons #'(pattern cond? skeleton) acc))
(()
(cons #'(pattern skeleton) acc))
))))))
(lambda (x)
(syntax-case x ()
((guarded-syntax-case y (literal ...) clause ...)
(with-syntax (((c ...) (fold-right add-clause '() #'(clause ...))))
#'(syntax-case y (literal ...) c ...)))))))
;;END
The macro was written for plt-r6rs
, but I wanted to experiment with it in the racket interpreter/REPL (, which is forbidden in racket's r6rs).
I couldn't make much progress except for adding the imports:
(require (for-meta 1 srfi/1))
Now when testing guarded-syntax-case
, I assumed that it is similar to racket/r6rs syntax-case
but with some added functionality. So I tested the following adapted example:
(syntax->datum
(guarded-syntax-case #'(+ 1 2) ()
[(op n1 n2) #'(- n1 n2)]))
but got an error:
. . null-list?: argument out of domain #<syntax:my-sweet.rkt:26:61 (((op n1 n2) (syntax (- n1 n2))))>
I couldn't figure out how to fix the error after a long time, since I am just beginning to learn macros.
Could some one please help explain why the macro doesn't work with racket, and how to make it work with racket?
I can only guess that the branch:
(()
(cons #'(pattern skeleton) acc))
is reached in the above example. I read that different scheme implementations can handle #'(pattern skeleton)
differently during conversion to/from syntax objects. So the cons
here could be a problem.
Upvotes: 2
Views: 122
Reputation: 820
(not an answer to the question but too long for comment):
One may observe that guarded-syntax-case
seems to be emulating
the standard R6RS fender option of syntax-case
, which is
available in Racket. The multi-define
example of using
guarded-syntax-case
in sweet-macros
can be written:
#lang racket
(require test-engine/racket-tests)
(define-syntax multi-define
(lambda (x)
(syntax-case x ()
[(_ (name ...) (value ...)) ; pattern
(or (= (length (syntax->datum #'(name ...))) ; fender ("guard")
(length (syntax->datum #'(value ...)))) ;
(raise-syntax-error 'multi-define "Names and values do not match" #f #f
(list #'(name ...) #'(value ...))))
#'(begin (define name value) ...) ]))) ; template ("skeleton")
(multi-define (a b) (1 2))
(check-expect a 1)
(check-expect b 2)
(multi-define (a b c) (1 2))
(test)
Upvotes: 1