Attached below is my preliminary attempt at functional record "setters".
These macros generate optimal code to generate a modified copy of an
existing tree of srfi-9 records, with any number of elements modified at
I confess that this task was more difficult than I had anticipated, and
it required a different approach than Ludovic had taken, because
functional single-field-setters cannot be used to build an optimal
Instead, each record type defines a '%%<TYPE-NAME>-modified-copy' macro
that copies a record but with an arbitrary number of modified fields.
This is the basis for the exported macros 'modified-copy' and
'modified-copy-nocheck' that supports arbitrarily nested records.
As Ludovic warned, this requires knowledge of the record types at
expansion time. To accomplish this, I enhanced srfi-9's private
'define-inlinable' macro to allow an arbitrary number of key/value pairs
to be associated with the generated macro. The new macro is called
'define-tagged-inlinable', and it's used like this:
(define-tagged-inlinable (key value) ... (name formals ...) body ...)
where each 'key' is a private literal identifier in (srfi srfi-9).
Currently, the keys '%%type', '%%index', and '%%copier' are associated
with each getter, which causes the getter macro to support additional
Since the keys are private to (srfi srfi-9), users cannot use these
private rules without accessing srfi-9's private symbols.
While I was at it, I incorporated Andy's suggestions
(accessors/modifiers => getters/setters, throw-bad-struct), and made
various other simplifications and improvements to the existing srfi-9
code, while being careful to remain ABI compatible with .go files
compiled with earlier versions of Guile 2.
Anyway, enough about the internals.
The public interface I've created is quite a bit different than what
we've been discussing so far. I'm open to changing it, but here's what
the attached patch currently exports from (srfi srfi-9 gnu):
These macros can be used on _any_ srfi-9 record, not just ones specially
declared as immutable. In fact, I have not yet gotten around to
creating immutable records (with "pr" layout), though I would like to
add this soon. However, I see no reason not to support 'modified-copy'
on mutable records as well.
@@ -68,8 +68,26 @@
;; because the public one has a different `make-procedure-name', so
;; using it would require users to recompile code that uses SRFI-9. See
+(define-syntax-rule (define-inlinable (name formals ...) body ...)
+ (define-tagged-inlinable () (name formals ...) body ...))
+;; 'define-tagged-inlinable' has an additional feature: it stores a map
+;; of keys to values that can be retrieved at expansion time. This is
+;; currently used to retrieve the rtd id, field index, and record copier
+;; macro for an arbitrary getter.
+(define %%type #f) ; a private syntax literal
+(define-syntax-rule (getter-type getter) (getter () %%type))
;;; srfi-9.scm ends here
diff --git a/module/srfi/srfi-9/gnu.scm b/module/srfi/srfi-9/gnu.scm
index 30c101b..d9c24a1 100644
@@ -1,6 +1,6 @@
;;; Extensions to SRFI-9
-;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2010, 2012 Free Software Foundation, Inc.
;; This library is free software; you can redistribute it and/or
;; modify it under the terms of the GNU Lesser General Public
@@ -23,8 +23,63 @@