[Top][All Lists]

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

G expressions

From: Ludovic Courtès
Subject: G expressions
Date: Thu, 24 Apr 2014 00:23:02 +0200
User-agent: Gnus/5.130009 (Ma Gnus v0.9) Emacs/24.3 (gnu/linux)


1. The Problem

There’s a recurrent problem that we need to communicate the file name of
store items to Scheme code that is going to live in another process:
expressions to build a derivation, Scheme files that are to be loaded by
other processes, etc.

This had been partly addressed by having ‘build-expression->derivation’
install two global variables in the build code: ‘%build-inputs’ and

However, for generated Scheme files (as in (gnu system) and related
modules), there’s no such mechanism.  Thus, either we use something

  (mlet %store-monad ((ls (package-file coreutils "bin/ls")))
    (text-file "foo" (object->string `(system* ,ls))))

but then the problem is that the resulting text file doesn’t hold a
reference to Coreutils, which is wrong.  Or, we do something like:

  (text-file* "foo" "(system* \"" coreutils "/bin/ls\")")

The resulting file does have a reference to Coreutils, but the approach
obviously sucks.

Besides, ‘%build-inputs’ is not particularly elegant either, and it’s
error-prone (if you refer to an input by the wrong name, you only notice
when building, with an obscure wrong-type-arg error.)  That’s been OK as
it’s only used occasionally in package recipes.

2. G Expressions

“G-expressions”, or gexps, are meant to address these two issues
mentioned above:

  1. Replacing a reference to a package or derivation by its output file

  2. Keeping track of the derivations it refers to.

In addition, the substitution in (1) must be done lazily, so that you
get the output file name for the ‘%current-system’ value when the gexp
is used.

The ‘gexp’ form is essentially like ‘quasiquote’, with ‘ungexp’ as the
counterpart of ‘unquote’:

  (gexp (system* (string-append (ungexp coreutils) "/bin/ls")))

That gexp can then be passed to ‘gexp->file’, which returns a derivation
that builds a file containing:

  (system* (string-append "/gnu/store/…" "/bin/ls"))

And it can also be used to describe derivation builds:

  (gexp->derivation "foo"
                        (mkdir (ungexp output))
                        (chdir (ungexp output))
                        (symlink (ungexp coreutils) "cu"))))

Note that we don’t need #:inputs here, because the gexp embeds that
info.  So eventually, we could even get rid of the label in the ‘inputs’
field of packages (not a priority, though.)

We could use some sugar to make it more concise (suggestions welcome):

  (gexp->derivation "foo"
                        (mkdir #$output)
                        (chdir #$output)
                        (symlink #$coreutils "cu")))

3. Conclusion

I think gexps can be helpful to serialize Scheme code that refers to
packages/derivations.  Preliminary work is in ‘wip-gexp’.
What do you think?

4. Related Work :-)

HOP has a quotation mechanism to introduce client-side code in server
code and vice-versa:

    :onclick ~(with-hop ($foo)))

Nix uses string interpolation to keep achieve what we do:

  script = ''${coreutils}/bin/ls'';

Here ${coreutils} is replaced by the output file name, and the resulting
string internally has additional info about the reference to that


Attachment: signature.asc
Description: PGP signature

reply via email to

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