Code Snippets

The Guix Workflow Language is embedded in Guile Scheme, so it makes sense to use Scheme to define the work that a process should perform. Sometimes it may be more convenient, though, to express the procedure in a different language, such as GNU R, Python, or maybe even in Bash.

The GWL provides special syntax for embedding code snippets. The special syntax is provided in the (gwl sugar) module, and is loaded by default. Here is an example of a process that runs an embedded Bash shell script:

process run-bash
  packages "bash"
  # bash { echo "hello from bash!" }

Notice how the “procedure” field name was not used here, because the code snippet came last. This cuts down on boilerplate.

Code snippets are introduced with # interpreter {, where interpreter is the command line for running an interpreter, such as /bin/bash -c. Code snippets must end with a closing brace, }.

Make sure that the package inputs include a package providing the interpreter. For convenience we provide the special interpreters bash, R, and python, so that you don’t have to specify a more complicated command line. When no interpreter is provided the generic shell interpreter /bin/sh will be used:

process run-sh
  # { echo "hello from a shell!" }

Within code snippets a special syntax is supported for accessing variables. Any uninterrupted value enclosed in double braces is considered a reference to a variable, which may also be the name of other process fields. In the following example, the shell snippet refers to the name and inputs fields of the current process:

process run-bash
  packages "bash"
  inputs
    . "a"
    . "b"
    . "c"
  # bash {
    echo "The name of this process: {{name}}."
    echo "The data inputs are: {{inputs}}."
  }

You can even access named or tagged values in lists. In the following example, the shell snippet refers to only selected values of the inputs field of the current process:

process run-bash
  packages "bash"
  inputs
    . "a"
    . mine: "b"
    . "c"
    . yours: "d"
  # bash {
    echo "This is mine: {{inputs:mine}}, and this is yours: {{inputs:yours}}."
  }

As expected, this will output the following text when run:

This is mine: b, and this is yours: d.

You can also access tagged sub-lists with the :: accessor:

process frobnicate
  packages "frobnicator"
  inputs
    . genome: "hg19.fa"
    . samples: "a" "b" "c"
  outputs
    . "result"
  # {
    frobnicate -g {{inputs:genome}} --files {{inputs::samples}} > {{outputs}}
  }

This process will cause the following command to be executed:

frobnicate -g hg19.fa --files a b c > result

If these two ways to access elements of a list are not enough, we recommend defining a variable using pick (Useful procedures and macros). In the following example we define a variable second-sample inside of the procedure field to hold the second of the inputs after the keyword samples:, i.e. the string the. We can then refer to that variable by name in the code snippet.

process foo
  inputs
    . "something"
    . samples: "in" "the" "way"
  procedure
    define second-sample
      pick second samples: inputs
    # { echo {{second-sample}} }

You can also access process meta data through environment variables. The following variables may be set: