I have a macro defined thus:
(define-syntax define-only (lambda (exp) (syntax-case exp () ((_ (n ...) e ...) (with-syntax (((tmp ...) (generate-temporaries (syntax (n ...))))) (syntax (begin (define n #f) ... (let ((tmp #f) ...) ((lambda () e ... (set! tmp n) ...)) (set! n tmp) ...))))))))
Which, if it works, would enable me to do the following:
(define-only (mkcounter inc! val) (define-structure counter v) ;; Invisible from the top-level. (define mkcounter (lambda () (make-counter 0))) (define inc! (lambda (c) (counter-v-set! c (+ 1 (counter-v c))))) (define val counter-v))
But which, unfortunately, gives me the following:
*** ERROR -- invalid context for definition (define mkcounter (lambda () (make-counter 0)))
I suspected that perhaps (define...)'s were not allowed after (define-structure...)'s. So I did this:
(pp (lambda () (define-structure test a) 'done))
Which prints the following:
(lambda () (letrec ((##type-1-test (##structure ##type-type (##make-uninterned-symbol "##type-1-test") 'test 8 #f '#(a 0 #f))) (make-test (lambda (p1) (##structure ##type-1-test p1))) (test? (lambda (obj) (##structure-direct-instance-of? obj (##type-id ##type-1-test)))) (test-a (lambda (obj) (##direct-structure-ref obj 1 ##type-1-test test-a))) (test-a-set! (lambda (obj val) (##direct-structure-set! obj val 1 ##type-1-test test-a-set!)))) 'done))
Which makes me wonder why my macro doesn't work. After all (define...)'s are allowed at the beginning of a letrec's body, no?
TJ
Afficher les réponses par date
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
From misc/syntax-case.scm:
; Note that Gambit's normal parser processes the ; input after expansion by the syntax-case expander. Since the ; syntax-case expander does not know about Gambit's syntactic ; extensions (like DSSSL parameters) some of the syntactic ; extensions cannot be used.
One of those Gambit extensions is define-structure. So the portable syntax-case expander thinks that
(define-structure ...)
is a function call, so it thinks the "define" that follows it is illegal.
I think this should work:
(define-only (mkcounter inc! val) (define-structure counter v) ;; Invisible from the top-level. (let () (define mkcounter (lambda () (make-counter 0))) (define inc! (lambda (c) (counter-v-set! c (+ 1 (counter-v c))))) (define val counter-v) #f))
Also, you can get around this problem by using your own definition for define-structure, for example this one from misc/psyntax73.scm:
(define-syntax define-structure (lambda (x) (define construct-name (lambda (template-identifier . args) (datum->syntax-object template-identifier (string->symbol (apply string-append (map (lambda (x) (if (string? x) x (symbol->string (syntax-object->datum x)))) args)))))) (syntax-case x () ((_ (name id1 ...)) (andmap identifier? (syntax (name id1 ...))) (with-syntax ((constructor (construct-name (syntax name) "make-" (syntax name))) (predicate (construct-name (syntax name) (syntax name) "?")) ((access ...) (map (lambda (x) (construct-name x (syntax name) "-" x)) (syntax (id1 ...)))) ((assign ...) (map (lambda (x) (construct-name x "set-" (syntax name) "-" x "!")) (syntax (id1 ...)))) (structure-length (+ (length (syntax (id1 ...))) 1)) ((index ...) (let f ((i 1) (ids (syntax (id1 ...)))) (if (null? ids) '() (cons i (f (+ i 1) (cdr ids))))))) (syntax (begin (define constructor (lambda (id1 ...) (vector 'name id1 ... ))) (define predicate (lambda (x) (and (vector? x) (= (vector-length x) structure-length) (eq? (vector-ref x 0) 'name)))) (define access (lambda (x) (vector-ref x index))) ... (define assign (lambda (x update) (vector-set! x index update))) ...)))))))
Marc
On 16-Apr-07, at 1:20 PM, TJ wrote:
I have a macro defined thus:
(define-syntax define-only (lambda (exp) (syntax-case exp () ((_ (n ...) e ...) (with-syntax (((tmp ...) (generate-temporaries (syntax (n ...))))) (syntax (begin (define n #f) ... (let ((tmp #f) ...) ((lambda () e ... (set! tmp n) ...)) (set! n tmp) ...))))))))
Which, if it works, would enable me to do the following:
(define-only (mkcounter inc! val) (define-structure counter v) ;; Invisible from the top-level. (define mkcounter (lambda () (make-counter 0))) (define inc! (lambda (c) (counter-v-set! c (+ 1 (counter-v c))))) (define val counter-v))
But which, unfortunately, gives me the following:
*** ERROR -- invalid context for definition (define mkcounter (lambda () (make-counter 0)))
I suspected that perhaps (define...)'s were not allowed after (define-structure...)'s. So I did this:
(pp (lambda () (define-structure test a) 'done))
Which prints the following:
(lambda () (letrec ((##type-1-test (##structure ##type-type (##make-uninterned-symbol "##type-1-test") 'test 8 #f '#(a 0 #f))) (make-test (lambda (p1) (##structure ##type-1-test p1))) (test? (lambda (obj) (##structure-direct-instance-of? obj (##type-id ##type-1-test)))) (test-a (lambda (obj) (##direct-structure-ref obj 1 ##type-1-test test-a))) (test-a-set! (lambda (obj val) (##direct-structure-set! obj val 1 ##type-1-test test-a-set!)))) 'done))
Which makes me wonder why my macro doesn't work. After all (define...)'s are allowed at the beginning of a letrec's body, no?
TJ _______________________________________________ Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
On 4/17/07, Marc Feeley feeley@iro.umontreal.ca wrote:
I think this should work:
(define-only (mkcounter inc! val) (define-structure counter v) ;; Invisible from the top-level. (let () (define mkcounter (lambda () (make-counter 0))) (define inc! (lambda (c) (counter-v-set! c (+ 1 (counter-v c))))) (define val counter-v) #f))
It doesn't work, because define-only is defined so that the expanded form becomes (simplified):
(begin (define mkcounter #f) (let ((tmp #f) ...) ((lambda () (define-structure counter v) ;; Invisible from the top-level. (let () (define mkcounter (lambda () (make-counter 0)))) (set! tmp mkcounter))) ; mkcounter refers to the top-level binding here, as the internal mkcounter has been wrapped up in a let. (set! mkcounter tmp)))
From misc/syntax-case.scm:
; Note that Gambit's normal parser processes the ; input after expansion by the syntax-case expander. Since the ; syntax-case expander does not know about Gambit's syntactic ; extensions (like DSSSL parameters) some of the syntactic ; extensions cannot be used.
One of those Gambit extensions is define-structure. So the portable syntax-case expander thinks that
I had to remove the (##namespace...) clauses at the beginning of syntax-case.scm because psyntax73.ss needed some procedures defined in syntax-case.scm which were, I presume, hidden by the namespace declarations. Also, I had to remove the (let () ...) clause surrounding most of psyntax73.ss, so that code outside of the let could actually use the stuff defined in psyntax73.ss. After removing the let I also had to move all the (define-syntax ...) forms to the front, before the (define ...)'s.
After that my code worked.
Here's my working code:
;; Begin code ------
(include "~/syntax-case.scm") ;; Edited syntax-case.scm (include "~/psyntax73.ss") ;; Edited psyntax73.ss
(define-syntax define-only (lambda (exp) (syntax-case exp () ((_ (n ...) e ...) (with-syntax (((tmp ...) (generate-temporaries (syntax (n ...))))) (syntax (begin (define n #f) ... (let ((tmp #f) ...) ((lambda () e ... (set! tmp n) ...)) (set! n tmp) ...))))))))
(define-only (mkcounter inc! val) (my-define-structure (counter v)) (define mkcounter (lambda () (make-counter 0))) (define inc! (lambda (c) (set-counter-v! c (+ 1 (counter-v c))))) (define val counter-v))
;; Do stuff here...
;; End code ------
With these in my gambcini.scm:
(load "~/syntax-case.scm") (load "~/gambc-4.0b22-charsize4/misc/psyntax73.ss")
So basically it works, but only after tweaking around.
TJ