Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

getting record type descriptor in the body of a macro

1 view
Skip to first unread message

Marco Maggi

unread,
Sep 11, 2009, 5:47:18 AM9/11/09
to
If I do:

(import (rnrs))

(define (print-fields rtd)
(write (record-type-field-names rtd))
(newline))

(define-syntax print-fields*
(syntax-rules ()
((_ ?record-name)
(print-fields (record-type-descriptor ?record-name)))))

(define-record-type alpha
(fields (mutable a)))

(print-fields* alpha)

everything works because PRINT-FIELDS* expands to a function
call, so the RECORD-TYPE-DESCRIPTOR form has a chance to
expand to the rtd. If I do:

(import (rnrs))

(define-syntax print-fields
(lambda (stx)
(define (print-fields rtd)
(write (record-type-field-names rtd))
(newline))
(syntax-case stx ()
((_ ?record-name)
(begin
;;This is wrong.
(print-fields (record-type-descriptor (syntax ?record-name)))
(syntax '(#f)))))))

(define-record-type alpha
(fields (mutable a)))

(print-fields alpha)

how do I give the RECORD-TYPE-DESCRIPTOR form a chance to
expand itself?

TIA
--
Marco Maggi

Aaron W. Hsu

unread,
Sep 11, 2009, 9:29:05 AM9/11/09
to
On Fri, 11 Sep 2009 05:47:18 -0400, Marco Maggi <mrc...@gmail.com> wrote:

> (import (rnrs))
>
> (define-syntax print-fields
> (lambda (stx)
> (define (print-fields rtd)
> (write (record-type-field-names rtd))
> (newline))
> (syntax-case stx ()
> ((_ ?record-name)
> (begin
> ;;This is wrong.
> (print-fields (record-type-descriptor (syntax ?record-name)))
> (syntax '(#f)))))))
>
> (define-record-type alpha
> (fields (mutable a)))
>
> (print-fields alpha)
>
> how do I give the RECORD-TYPE-DESCRIPTOR form a chance to
> expand itself?

In short, you need to make sure that the record type is visible at
expansion time rather than run-time. That is, body of the lambda is
evaluated at the expansion phase, where the bindings for alpha do not
exist.

There are a few ways to manage this. You can use R6RS Libraries to import
the record name into the correct phase (this may or may not be done
implicitly by your Scheme implementation), or you can use the 'meta'
functionality of your Scheme, which most Schemes provide.

In Chez Scheme, which does implicit phasing, you could have two different
libraries or you could use 'meta'.

--- Using two libraries ---
(library (record)
(export alpha)
(import (rnrs records syntactic))
(define-record-type alpha (fields (mutable a))))

(library (main)
(export)
(import (rnrs) (record))

(define-syntax print-fields
(lambda (stx)
(define (print-fields rtd)
(write (record-type-field-names rtd))
(newline))
(syntax-case stx ()
((_ ?record-name)
(begin
;;This is wrong.
(print-fields (record-type-descriptor (syntax ?record-name)))
(syntax '(#f)))))))

(print-fields alpha)

)

--- Using 'meta' ---
(import (chezscheme))

(meta define-record-type alpha (fields (mutable a)))

(define-syntax print-fields
(lambda (stx)
(define (print-fields rtd)
(write (record-type-field-names rtd))
(newline))
(syntax-case stx ()
((_ ?record-name)
(begin
;;This is wrong.
(print-fields (record-type-descriptor (syntax ?record-name)))
(syntax '(#f)))))))

(print-fields alpha)


Sincerely,

Aaron W. Hsu

--
Of all tyrannies, a tyranny sincerely exercised for the good of its
victims may be the most oppressive. -- C. S. Lewis

marcomaggi

unread,
Sep 12, 2009, 2:02:40 AM9/12/09
to
On Sep 11, 3:29 pm, "Aaron W. Hsu" <arcf...@sacrideo.us> wrote:
> In short, you need to make sure that the record type is visible at  
> expansion time rather than run-time. That is, body of the lambda is  
> evaluated at the expansion phase, where the bindings for alpha do not  
> exist.

I came up with the following which works with LIMY[1] Schemes:

(library (lib)
(export alpha)
(import (rnrs))


(define-record-type alpha
(fields (mutable a))))

;;;program
(import (rnrs)
(for (lib) expand run))

(define-syntax print-fields
(syntax-rules ()
((_ ?record-name)
(let-syntax ((A (lambda (stx)
(define (%print-fields)
(write (record-type-field-names
(record-type-descriptor ?record-name)))
(newline))
(syntax-case stx ()
((_)
(begin
(%print-fields)
(syntax '())))))))
(A)))))

(print-fields alpha)
;;;end of program

only Larceny requires the "for --- expand", all the others are happy
with a plain import. I am not sure to understand why I have to import
the library for expand; R6RS says about the <record name> in the
description of DEFINE-RECORD-TYPE:

"it is bound by this definition to an expand-time or run-time
representation of the record type"

does this mean that all the LIMY implementations choose to bind it
only at run-time? So, the syntax RECORD-TYPE-DESCRIPTOR does not do
the work itself, rather it expands to a function call which does the
work (or it expands to the binding itself)?

[1] Larceny, Ikarus, Mosh, Ypsilon.
--
Marco Maggi

0 new messages