unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Fancy records in Guix
@ 2012-11-03 23:13 Ludovic Courtès
  0 siblings, 0 replies; only message in thread
From: Ludovic Courtès @ 2012-11-03 23:13 UTC (permalink / raw)
  To: guile-user

Hello Guilers,

I thought I’d share a bit about the “fancy” record constructs in
Guix [0], which provide syntactic constructors, default field values,
and “functional” setters.

Guix is about manipulating packages, which are essentially records with
many fields.  Thus, I wanted the ability to create new record instances
using field names (à la SRFI-35), and to have field name checks and
name-to-offset mappings happen at compile-time, so one could type things
like:

    (package
      (name "hello")
      (version "2.8")
      (source (origin
               (method http-fetch)
               (uri (string-append "http://ftp.gnu.org/gnu/hello/hello-"
                                   version  ; refers to the “2.8” above
                                   ".tar.gz"))
               (sha256
                (base32 "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6"))))
      (build-system gnu-build-system)
      (description "GNU Hello")
      (long-description "Yeah...")
      (home-page "http://www.gnu.org/software/hello/")
      (license "GPLv3+"))

and have it directly expand to a single ‘make-struct’ call, with missing
or unknown fields reported at compile-time.

In addition, there may be default field values.  For instance, the
‘location’ field should default to (current-source-location).

So I ended up with a ‘define-record-type*’ macro, based on SRFI-9, which
is used like this:

  (define-record-type* <package>
    package        ; the “syntactic” constructor used above
    make-package   ; the procedural constructor

    package?
    (name   package-name)
    (version package-version)
    (source package-source)

    ;; ...

    (location package-location
              (default (and=> (current-source-location)
                              source-properties->location))))

Finally, these syntactic record constructors support “functional
setters”, where a new record instance is created with some fields copied
from an existing instance, and others set to a new value:

   (package (inherit coreutils)
     (arguments
      `(#:configure-flags
        '("--disable-nls"
          "--disable-silent-rules"
          "--enable-no-install-program=stdbuf,libstdbuf.so"
          "LDFLAGS=-static -pthread")
        ,@(package-arguments coreutils))))

Here field values are those of the ‘coreutils’ variable, except for the
‘arguments’ field.

The code for this macro magic is at
<https://gitorious.org/guix/guix/blobs/master/guix/utils.scm#line484>.

Happy hacking!

Ludo’.

[0] https://gitorious.org/guix




^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2012-11-03 23:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-03 23:13 Fancy records in Guix Ludovic Courtès

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).