[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Functional record "setters", a different approach
From: |
Ludovic Courtès |
Subject: |
Re: Functional record "setters", a different approach |
Date: |
Sat, 10 Nov 2012 17:28:57 +0100 |
User-agent: |
Gnus/5.130005 (Ma Gnus v0.5) Emacs/24.2 (gnu/linux) |
Hello!
Documentation attached. Comments?
BTW, why does ‘set-field’ has the record as its 2nd argument instead of
1st (unlike ‘set-fields’)?
Thanks,
Ludo’.
>From f7877d47009dc85e74bc63fd562b77f552a54bd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <address@hidden>
Date: Sat, 10 Nov 2012 17:27:14 +0100
Subject: [PATCH] doc: Document SRFI-9 functional setters.
* doc/ref/api-compound.texi (Functional ``Setters''): New section.
---
doc/ref/api-compound.texi | 101 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
diff --git a/doc/ref/api-compound.texi b/doc/ref/api-compound.texi
index b3fe0bd..0451368 100644
--- a/doc/ref/api-compound.texi
+++ b/doc/ref/api-compound.texi
@@ -2398,6 +2398,107 @@ This example prints the employee's name in brackets,
for instance @code{[Fred]}.
(write-char #\] port)))
@end example
address@hidden Functional ``Setters''
+
address@hidden functional setters
+
+When writing code in a functional style, it is desirable to never alter
+the contents of records. For such code, a simple way to return new
+record instances based on existing ones is highly desirable.
+
+The @code{(srfi srfi-9 gnu)} module extends SRFI-9 with facilities to
+return new record instances based on existing ones, only with one or
+more field values address@hidden setters}. First, the
address@hidden works like
address@hidden, except that setters are defined as functional
+setters.
+
address@hidden {Scheme Syntax} define-immutable-record-type type @*
(constructor fieldname @dots{}) @* predicate @* (fieldname accessor [modifier])
@dots{}
+Define @var{type} as a new record type, like @code{define-record-type}.
+However, the record type is made @emph{immutable} (records may not be
+mutated, even with @code{struct-set!}), and any @var{modifier} is
+defined to be a functional setter---a procedure that returns a new
+record instance with the specified field changed, and leaves the
+original unchanged (see example below.)
address@hidden deffn
+
address@hidden
+In addition, the generic @code{set-field} and @code{set-fields} macros
+may be applied to any SRFI-9 record.
+
address@hidden {Scheme Syntax} set-field (field sub-fields ...) record value
+Return a new record of @var{record}'s type whose fields are equal to
+the corresponding fields of @var{record} except for the one specified by
address@hidden
+
address@hidden must be the name of the getter corresponding to the field of
address@hidden being ``set''. Subsequent @var{sub-fields} must be record
+getters designating sub-fields within that field value to be set (see
+example below.)
address@hidden deffn
+
address@hidden {Scheme Syntax} set-fields record ((field sub-fields ...) value)
...
+Like @code{set-field}, but can be used to set more than one field at a
+time. This expands to code that is more efficient than a series of
+single @code{set-field} calls.
address@hidden deffn
+
+To illustrate the use of functional setters, let's assume these two
+record type definitions:
+
address@hidden
+(define-record-type <address>
+ (address street city country)
+ address?
+ (street address-street)
+ (city address-city)
+ (country address-country))
+
+(define-immutable-record-type <person>
+ (person age email address)
+ person?
+ (age person-age set-person-age)
+ (email person-email set-person-email)
+ (address person-address set-person-address))
address@hidden example
+
address@hidden
+First, note that the @code{<person>} record type definition introduces
+named functional setters. These may be used like this:
+
address@hidden
+(define fsf-address
+ (address "Franklin Street" "Boston" "USA"))
+
+(define rms
+ (person 30 "rms@@gnu.org" fsf-address))
+
+(and (equal? (set-person-age rms 60)
+ (person 60 "rms@@gnu.org" fsf-address))
+ (= (person-age rms) 30))
address@hidden #t
address@hidden example
+
address@hidden
+Here, the original @code{<person>} record, to which @var{rms} is bound,
+is left unchanged.
+
+Now, suppose we want to change both the street and age of @var{rms}.
+This can be achieved using @code{set-fields}:
+
address@hidden
+(set-fields rms
+ ((person-age) 60)
+ ((person-address address-street) "Temple Place"))
address@hidden #<<person> age: 60 email: "rms@@gnu.org"
+ address: #<<address> street: "Temple Place" city: "Boston" country: "USA">>
address@hidden example
+
address@hidden
+Notice how the above changed two fields of @var{rms}, including the
address@hidden field of its @code{address} field, in a concise way. Also
+note that @code{set-fields} works equally well for types defined with
+just @code{define-record-type}.
@node Records
@subsection Records
--
1.7.10.4
- Re: Functional record "setters", a different approach, Mark H Weaver, 2012/11/07
- Re: Functional record "setters", a different approach, Mark H Weaver, 2012/11/08
- Re: Functional record "setters", a different approach, Ludovic Courtès, 2012/11/08
- Re: Functional record "setters", a different approach, Mark H Weaver, 2012/11/08
- Re: Functional record "setters", a different approach,
Ludovic Courtès <=
- Re: Functional record "setters", a different approach, Mark H Weaver, 2012/11/10
- Re: Functional record "setters", a different approach, Ludovic Courtès, 2012/11/10
- Re: Functional record "setters", a different approach, Mark H Weaver, 2012/11/09