[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Scheme-reports] quasisyntax extension

Dear members,

Consider the code at the bottom of the mail defining an extension (in guile),

with this I can enter code like

(define (f x)
    #`(let ((x 1)) #,x))

(define-syntax g
  (lambda (x)
    (syntax-case x ()
      ((_ y)
        ##`(let ((x y)) #.((x) (f #'x)))))))

and get

scheme@(guile-user)> (g 4)
$1 = 4

note #. assumes #.((pat ...) c ...) where (begin c ...) will produce what's inserted under the variable captures defined by pat....
via a let-syntax mechanism,

If we would write the above using #` and #, in racket and guile that would produce 1 in stead.

This construction can probably be styled more simply by assuming the variable bindings implicitly and
realized by hacking psyntax (which I do not want to do to show the semantics) so ideally I would have liked
to write #.(f #'x) as a cleaner form.

I do know that writing macro expansions in this way is considered bad style but do not know why. I tend to like the
idea of writing macro expansions with a minimum of helper macros, The fact that you need a lot of helper macros
when writing for example a matcher in the traditional style with e.g. syntax-rule is something I view as unclean
and limiting.

My ideal of handling for example an implementation of the racket macther, see


Is using syntax-parse to destruct the code in it's components and then build up the resulting expansion using functions and making
heavy use of #` and friends. Testing this approach I got into problems with capturing variable bindings in the spirit of the above example,
and the solution at that time was to go back with Common Lisp like gensyming. A better solution would be to use ##` and #. in stead for a cleaner and more (I believe) syntactically correct solution. Anyhow what do you think about introducing these constructs in a more un hackky way to scheme in general (at least those using psyntax and similar macro systems) in order to let people code more safely with the suggested

How is this style differnt from using macros? It allows the construction flow with many different channels of
information, channels that is non syntax and channels that are syntax objects! It have the functional applicational

Anyhow I would like to try to lift this semantic to a more general platform if possible cause I find it a really nifty feature.



(define *s* (make-fluid '()))

(define (parse stx x)
  (syntax-case x (unsyntax insyntax unsyntax-splicing)
    ((unsyntax          . _) x)
    ((unsyntax-splicing . _) x)
    ((insyntax ((p ...) c ...))
     (with-syntax ((g (datum->syntax stx (gensym "g"))))
       (fluid-set! *s* (cons #'(g (lambda (x)
      (syntax-case x ()
                                      ((_ p ...) #t (begin c ...)))))
                             (fluid-ref *s*)))
       #'(g p ...)))
    ((x . l)
     (cons (parse stx #'x) (parse stx #'l)))
    (x #'x)))

(define-syntax quasisyntax++
  (lambda (x)
    (syntax-case x ()
      ((_ y)
         (fluid-set! *s* '())
         (with-syntax ((statement (parse x #'y))
                       (lets      (fluid-ref *s*)))
           #'(quasisyntax (let-syntax lets statement))))))))
(define (rg ch stream)
  (let ((x (read-char stream)))
     ((eqv? x #\`)
      `(quasisyntax++ ,(read stream)))
      (error "Wrong format of # reader extension")))))

(define (rg. ch stream) `(insyntax ,(read stream)))

(read-hash-extend #\# rg)
(read-hash-extend #\. rg.)
Scheme-reports mailing list