manpagez: man pages & more
info guile
Home | html | info | man
[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

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 (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 changed—functional setters. First, the define-immutable-record-type works like define-record-type, except that fields are immutable and setters are defined as functional setters.

Scheme Syntax: define-immutable-record-type type
(constructor fieldname …)
predicate
(fieldname accessor [modifier]) …

Define type as a new record type, like define-record-type. However, the record type is made immutable (records may not be mutated, even with struct-set!), and any 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.)

In addition, the generic set-field and set-fields macros may be applied to any SRFI-9 record.

Scheme Syntax: set-field record (field sub-fields ...) value

Return a new record of record’s type whose fields are equal to the corresponding fields of record except for the one specified by field.

field must be the name of the getter corresponding to the field of record being “set”. Subsequent sub-fields must be record getters designating sub-fields within that field value to be set (see example below.)

Scheme Syntax: set-fields record ((field sub-fields ...) value) ...

Like 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 set-field calls.

To illustrate the use of functional setters, let’s assume these two record type definitions:

(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))

First, note that the <person> record type definition introduces named functional setters. These may be used like this:

(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))
⇒ #t

Here, the original <person> record, to which rms is bound, is left unchanged.

Now, suppose we want to change both the street and age of rms. This can be achieved using set-fields:

(set-fields rms
  ((person-age) 60)
  ((person-address address-street) "Temple Place"))
⇒ #<<person> age: 60 email: "rms@gnu.org"
  address: #<<address> street: "Temple Place" city: "Boston" country: "USA">>

Notice how the above changed two fields of rms, including the street field of its address field, in a concise way. Also note that set-fields works equally well for types defined with just define-record-type.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated on April 20, 2013 using texi2html 5.0.

© manpagez.com 2000-2024
Individual documents may contain additional copyright information.