guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Fancy records in Guix


From: Ludovic Courtès
Subject: Fancy records in Guix
Date: Sun, 04 Nov 2012 00:13:56 +0100
User-agent: Gnus/5.130005 (Ma Gnus v0.5) Emacs/24.2 (gnu/linux)

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]