Hi!

Noah Lavine <noah.b.lav...@gmail.com> skribis:

> Since updating a field requires creating a new record object (I
> think), it seems useful to have an interface to update many fields at
> once, to avoid creating many temporary objects.

Yes, others mentioned it on IRC, though I’m wondering how common this is
in practice.

> In the spirit of brainstorming, I have two ideas to offer. First,
> here's an extended version of your example:
>
>  (let* ((p1 (set-field (person-address address-city) p "Düsseldorf"))
>          (p2 (set-field (age) p1 32))))
>
> 1. Alternate a lists of field names and values. The example becomes
>   (set-field p (person-address address-city) "Düsseldorf" (age) 32)

I prefer this one.  Perhaps it could be called ‘set-fields’, even.

However, generating the most optimal code may prove to be complicated.
For instance, you’d want:

  (set-fields p (person-address address-city) "Düsseldorf"
                (person-address address-street) "Bar")

to expand to:

  (set-person-address p
                      (let ((a (person-address p)))
                        (set-fields a (address-city) "Düsseldorf"
                                      (address-street) "Bar")))

But that would require knowledge of the relationship between
‘address-city’, ‘address-street’, and the underlying record type, etc.

Instead, I think I’ll add ‘record-copy’, similar to Racket’s
‘struct-copy’ [0], as Ian Price suggested on IRC.  We can do this
because it turns out that our SRFI-9 records are now “Guile records”,
and thus they have a run-time type descriptor that maps field names to
their indices.

The drawback compared to generated setters as above is that field lookup
happens at run-time, which degrades performance and delays any error
report to execution time.

Thanks,
Ludo’.

[0] http://docs.racket-lang.org/reference/struct-copy.html

Reply via email to