R6RS records and exports

8 views
Skip to first unread message

Grant Rettke

unread,
Feb 28, 2009, 8:21:00 AM2/28/09
to
Records conveniently generate a constructure and getters and setters
for you.

Is there a way to conveniently export all these generated functions?

I am thinking of generating a helper function so I can copy and paste
the exports; this is not ideal of course.

kub

unread,
Feb 28, 2009, 9:49:04 AM2/28/09
to

The only way to export whole record type by exporting single
identifier is some wrapping macro which allows you to access all other
record elements.
For example I have simple experimental define-properties, ~, using
macros which can be used like following:


(library (graphics)
(export Color)
(import ...)

; Original record type
(define-record-type color
(fields
red green blue))

; Wrapper
(define-properties Color
(record-type-descriptor color) ; When using Color as variable
; properties accessable via '~ operator
[red color-red]
[green color-green]
[blue color-blue]
[make make-color]
[isa? color?])
...

(import (only (graphics) Color))

(display (~ Color red)) => #<procedure:color-red>

(let ([c ((~ Color make) 10 20 30)])
(display c) ;=> #<struct:color 10 20 30>
(display ((~ Color isa?) c))) ;=> #t
;; Now same as prior but via 'using macro
(using Color
(let ([c (make 10 20 30)])
(display c) ;=> #<struct:color 10 20 30>
(display (isa? c))) ;=> #t

Also you can invent more convenient syntax, but it is another story.
BTW, I'd like original define-record-type work without wrapper, but
most of Scheme community is too biased to current semantics.
AFAIR there was post by Kent Dybwig (in r6rs lists) who proposed some
other solution to your problem but there wasn't much interest and it
was beaten by some semi-logic arguments.
IMHO it is big problem of standard but it is my personal opinion.

--
Bogdan

Aaron W. Hsu

unread,
Feb 28, 2009, 11:39:21 AM2/28/09
to
Grant Rettke <gre...@gmail.com> writes:

To my knowledge,there is no facility in R6RS for doing bulk exports of
any kind or any group of identifiers. They have to be written out by
hand. So, a generator is pretty much all you can do, assuming you copy
and paste the output.
--
Aaron W. Hsu <arc...@sacrideo.us> | <http://www.sacrideo.us>
"Government is the great fiction, through which everybody endeavors to
live at the expense of everybody else." -- Frederic Bastiat
+++++++++++++++ ((lambda (x) (x x)) (lambda (x) (x x))) ++++++++++++++

Abdulaziz Ghuloum

unread,
Feb 28, 2009, 2:55:16 PM2/28/09
to
Grant Rettke wrote:
> Records conveniently generate a constructure and getters and setters
> for you.
>
> Is there a way to conveniently export all these generated functions?

No.

> I am thinking of generating a helper function so I can copy and paste
> the exports; this is not ideal of course.

Of course.

But there is a workaround. (I can't bet on the portability
of the proposed solution, but I see nothing in the report
that disallows it. It works under Ikarus.)

When you import a record type, you can use the r6rs inspection
facilities to obtain the record type descriptor which contains
most of the information that you'd need. It gives you the
constructor descriptor through which you can obtain a record
constructor procedure. It gives you the ability to make a record
predicate. It also gives you the count and names (and mutability)
of the record fields in order for you to construct the accessors
(and mutators if needed).

In Ikarus, and though implicit phasing, this information is
available for you both at expansion-time and at run-time. So,
you can easily pick and match the pieces of data that you want
without problems. This is one reason why I can't bet on its
portability.

Anyways, here is a sketch of the library that solution. It uses
no Ikarus-specific libraries.

Aziz,,,

;;; redefine-record.sls

(library (redefine-record)
(export redefine-record-type)
(import (rnrs))
(define-syntax redefine-record-type
(syntax-rules ()
[(_ record-name)
(begin
(define-syntax m
(lambda (x)
(define (fmt s1 stx . s*)
(datum->syntax stx
(string->symbol
(apply string-append
s1
(symbol->string (syntax->datum stx))
s*))))
(define (enumerate i j)
(if (= i j) '() (cons i (enumerate (+ i 1) j))))
(syntax-case x ()
[(_ ctxt)
(let* ([rtd (record-type-descriptor
record-name)]
[f* (record-type-field-names rtd)]
[rcd (record-constructor-descriptor
record-name)])
(with-syntax ([make-T (fmt "make-" #'ctxt)]
[T? (fmt "" #'ctxt "?")]
[(n* (... ...))
(enumerate 0 (vector-length f*))]
[#(T-ref* (... ...))
(vector-map
(lambda (x)
(fmt "" #'ctxt "-" (symbol->string
x)))
f*)])
#'(begin
(define make-T
(record-constructor
(record-constructor-descriptor
record-name)))
(define T?
(record-predicate
(record-type-descriptor
record-name)))
(define T-ref*
(record-accessor
(record-type-descriptor record-name)
n*))
(... ...))))])))
(m record-name))])))

;;; t1.sls

(library (t1)
(export M)
(import (rnrs))
(define-record-type M
(fields x y z)))

;;; t2.ss

(import (rnrs) (t1) (redefine-record))

(redefine-record-type M)

(define x (make-M 12 13 14))
(display (list x (M? x) (M-x x)))
(newline)

$ ikarus --r6rs-script t2.ss
(#[M 12 13 14] #t 12)

andreu...@yahoo.com

unread,
Mar 2, 2009, 12:42:00 PM3/2/09
to
On Feb 28, 11:55 am, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:

> But there is a workaround.  (I can't bet on the portability
> of the proposed solution, but I see nothing in the report
> that disallows it.  It works under Ikarus.)

It works under Larceny as well as long as you replace the line

(import (rnrs) (t1) (redefine-record))

by

(import (rnrs) (for (t1) expand run) (redefine-record))

As far as I can tell, this is all that is needed to make the program
R6RS-portable.

Abdulaziz Ghuloum

unread,
Mar 2, 2009, 1:35:05 PM3/2/09
to

I thought there was more, like that R6RS does not specify
whether the identifier foo in (define-record-type foo ...)
is exportable or not (I don't recall who made this claim
and didn't verify its validity).

Aziz,,,

Michael Sperber

unread,
Mar 3, 2009, 2:20:49 AM3/3/09
to

Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> I thought there was more, like that R6RS does not specify
> whether the identifier foo in (define-record-type foo ...)
> is exportable or not (I don't recall who made this claim
> and didn't verify its validity).

I don't know why it would not be exportable: The spec talks says that
`define-record-type' creates bindings, and then goes into detail as to
what the binding of the record-type identifier is.

--
Cheers =8-} Mike
Friede, Völkerverständigung und überhaupt blabla

William D Clinger

unread,
Mar 3, 2009, 10:58:33 AM3/3/09
to
Mike Sperber quoting Aziz Ghuloum:

> > I thought there was more, like that R6RS does not specify
> > whether the identifier foo in (define-record-type foo ...)
> > is exportable or not (I don't recall who made this claim
> > and didn't verify its validity).
>
> I don't know why it would not be exportable: The spec talks says that
> `define-record-type' creates bindings, and then goes into detail as to
> what the binding of the record-type identifier is.

Here's what R6RS library section 6.2 says about the binding
of foo:

<Record name>, taken as a symbol, becomes the name
of the record type. (See the description of
make-record-type-descriptor below.) Additionally, it
is bound by this definition to an expand-time or
run-time representation of the record type and can
be used as parent name in syntactic record-type
definitions that extend this definition. It can also
be used as a handle to gain access to the underlying
record-type descriptor and constructor descriptor
(see record-type-descriptor and
record-constructor-descriptor below).

Notice that foo is bound to "an expand-time or run-time
representation" and can "be used as a handle"; evidently
foo is not an ordinary variable or macro, which are the
only things that the R6RS describes as being exportable
from a library.

I suspect that most implementors of the R6RS have chosen
to extend the R6RS by exporting record types bound by
define-record-type, but I am pretty sure this extension
is not required by the R6RS itself. If someone were to
build a truly R6RS-conforming implementation that attempts
to perform all of the punitive portability checking
mandated or suggested by the R6RS, that implementation
might well reject any attempt to export a record type.

Will

Michael Sperber

unread,
Mar 4, 2009, 2:58:37 AM3/4/09
to

William D Clinger <cesu...@yahoo.com> writes:

> Notice that foo is bound to "an expand-time or run-time
> representation" and can "be used as a handle"; evidently
> foo is not an ordinary variable or macro, which are the
> only things that the R6RS describes as being exportable
> from a library.

The operative is "binding". From the library chapter of R6RS:

>> The `export' subform specifies a list of exports, which name
>> a subset of the bindings defined within or imported into the
>> library.

In any case, making the record type non-exportable was clearly not the
intention of anyone who wrote the above. (Mostly me, so I think I know.
You being co-author of SRFI 76, where the same wording occurs, it may
have been your intention, though.) Also, the word "ordinary" doesn't
even appear in the library chapter, so I don't know how you would use it
to distinguish the bindings referred to in the library chapter and the
bindings referred to in the records chaper. Moreover, I don't see the
way the binding is used has any impact on exportability.

As always, I'd be happy to add an erratum if anybody could suggest a
wording that makes this more clear.

> I suspect that most implementors of the R6RS have chosen
> to extend the R6RS by exporting record types bound by
> define-record-type, but I am pretty sure this extension
> is not required by the R6RS itself. If someone were to
> build a truly R6RS-conforming implementation that attempts
> to perform all of the punitive portability checking
> mandated or suggested by the R6RS, that implementation
> might well reject any attempt to export a record type.

As usual, it was too much to expect a constructive comment from you, and
you couldn't resist to insert the n-th repetition of one of your
propaganda statements (do you really think anybody here hasn't heard it
before?), instead of sticking with a useful task, which in this case
might have been to clarify and fix ambiguities and inconsistencies in
the wording of the standard so the community can benefit.

Given how little the propaganda has to do with the issue at hand, I
wonder if you have an e-mail postprocessor that just adds them add
random to any posting with "R6RS" in it. If you'd spent as much care
looking for nits in the predecessors of R6RS, my job trying to rectify
them in R6RS sure would have been a lot easier. On the other hand, if
you'd voiced your nits in the same way as you do now, Scheme might be
even closer to moribundity than it already is. So on balance I guess
I'm glad you didn't, even though I've come to believe it won't make a
difference in the long run.

William D Clinger

unread,
Mar 4, 2009, 8:10:39 AM3/4/09
to
Mike wrote:
> The operative is "binding".

Yes. But what does it mean to export a "binding"?
The R6RS base document answers that question only for
variables (which are the only run-time bindings it
discusses) and macros (which are the only expand-time
bindings it discusses). R6RS 7.2 appears to confirm
that interpretation:

Every library can be characterized by expand-time
information (minimally, its imported libraries, a
list of the exported keywords, a list of the
exported variables, and code to evaluate the
transformer expressions) and run-time information
(minimally, code to evaluate the variable definition
right-hand-side expressions, and code to evaluate
the body expressions). The expand-time information
must be available to expand references to any
exported binding, and the run-time information must
be available to evaluate references to any exported
variable binding.

> As always, I'd be happy to add an erratum if anybody
> could suggest a wording that makes this more clear.

The real issue is Occam's Razor: Thou shalt not multiply
entities beyond necessity. You are still talking as
though the problem is that you simply forgot to specify
all the new entities you introduced.

Will

Michael Sperber

unread,
Mar 5, 2009, 2:10:54 AM3/5/09
to

William D Clinger <cesu...@yahoo.com> writes:

> Yes. But what does it mean to export a "binding"?
> The R6RS base document answers that question only for
> variables (which are the only run-time bindings it
> discusses) and macros (which are the only expand-time
> bindings it discusses).

Yes. And the intention of the wording in the records chapter was to say
that it must be one of those two. The problem may be that I was
reluctant to use the word "macro" for something that can't be used in
the form (<keyword> ...).

> The real issue is Occam's Razor: Thou shalt not multiply entities
> beyond necessity. You are still talking as though the problem is that
> you simply forgot to specify all the new entities you introduced.

Then you misunderstand me.

Reply all
Reply to author
Forward
0 new messages