VOID404
VOID404

Reputation: 35

Literals in syntax-rules don't work in libraries in Scheme

I want to define new syntax. If I define it without a library, just

(define-syntax sample1
  (syntax-rules (:times)
    [(_ n :times body ...)
     (list n (sample1 body ...))]
    [(c body ...)
     '(body ...)]))

it works as expected, but if I put it in a library:

(library (alib)
  (export sample2)
  (import
    (rnrs))
  (define-syntax sample2
    (syntax-rules (:times)
      [(_ n :times body ...)
       (list n (sample2 body ...))]
      [(c body ...)
       '(body ...)])))

the :times literal stops working. It works if I replace :times with a literal present in an already existing macro, like => or else.

Here's full example in Chez:

(define-syntax sample1
    (syntax-rules (:times)
      [(_ n :times body ...)      
       (list n (sample1 body ...))]
      [(c body ...)
       '(body ...)]))
(sample1 a b c d)
;; => (a b c d)

(sample1 10 :times a b c d)
;; => (10 (a b c d))

(library (alib)      
    (export sample2)
    (import 
      (rnrs))
    (define-syntax sample2
      (syntax-rules (:times)
        [(_ n :times body ...)      
         (list n (sample2 body ...))]
        [(c body ...)
         '(body ...)])))
(import (alib))
(sample2 10 :times a b c d)
;; => (10 :times a b c d)

Upvotes: 1

Views: 120

Answers (2)

Peter Winton
Peter Winton

Reputation: 786

You can use fender expressions as an alternative to auxiliary keywords.

(library (alib)
  (export sample2)
  (import
   (chezscheme)) ;; <= required for syntax-rules fenders
  (define-syntax sample2
    (syntax-rules ()
      [(_ n :times body ...)
       (eq? (datum :times) ':times) ;; <= fender
       (list n (sample2 body ...))]
      [(c body ...)
       '(body ...)])))
(import (alib))
(sample2 10 :times a b c d) ;; => (10 (a b c d))

Define a keyword? macro to make the fender cleaner.

(library (meta)
  (export keyword?)
  (import (chezscheme))
  (define-syntax keyword?
    (syntax-rules ()
      [(_ x) (eq? (datum x) 'x)])))

(library (alib)
  (export sample2)
  (import (meta) (chezscheme))
  (define-syntax sample2
    (syntax-rules ()
      [(_ n :times body ...)
       (keyword? :times)
       (list n (sample2 body ...))]
      [(c body ...)
       '(body ...)])))
(import (alib))
(sample2 10 :times a b c d) ;; => (10 (a b c d))

Upvotes: 0

mnemenaut
mnemenaut

Reputation: 820

This seems to work:

Chez Scheme Version 9.5.7.6

> (library (alib)      
      (export sample2 :times)
      (import 
        (rnrs))
      (define :times #f)
      (define-syntax sample2
        (syntax-rules (:times)
          [(_ n :times body ...)      
           (list n (sample2 body ...))]
          [(_ body ...)
           '(body ...)])))
> (import (alib))
> (sample2 10 :times a b c d)
(10 (a b c d))
>

To use a literal (auxiliary keyword) in multiple libraries, define in a library imported by the syntax defining libraries:

(library (literals)
  (export :times)
  (import (rnrs))
  (define :times #f))

(library (alib)      
      (export sample1 :times)
      (import (rnrs) (literals))
      (define-syntax sample1
        ...
(library (blib)      
      (export sample2 :times)
      (import (rnrs) (literals))
      (define-syntax sample2
        ...

Upvotes: 1

Related Questions