“hello ${{a=“1”; b=“2”;}.b}” “1 2 ${toString 3}” “${pkgs.bash}/bin/sh”

Data types

/etc ./foo.png ~/.config

{ foo.bar = 1; } { foo = { bar = 1; }; }

rec {}

Primitives

  • String “foo bar” ’' foo bar ’' “foo\nbar\n”
    • string interpolation ${} ‘’${} ‘’\n
  • Number 123 .23e13
  • Path /bin/sh ./builder.sh (relative to the directory of the Nix expression that contained it) ~/foo at least one slash must appear before any interpolated expresssion. <>
  • Boolean true and false
  • Null null

List

[ 123 “jfalkdjf” ./foo.nix (f {x=y;}) ] builtins.elemAt

Attribute Set

A collection of name-value-pairs (called attributes) identifier: [a-zA-Z_][a-zA-Z0-9_'-]* name : identifier | string attrset : {[name = expr;]...}

. operator or keyword

{ a = "Foo"; b = "Bar"; }.c.d.e.f.g or "Xyzzy"

Attr names string interpolation:

let bar = "foo"; in
{ foo = 123; }.${bar}

let bar = "foo"; in
{ ${bar} = 123; }.foo

{ ${if foo then "bar" else null} = true; }

__functor

let add = { __functor = self: x: x + self.x; };
    inc = add // { x = 1; };
in inc 1

Recursive sets

rec-attrset: rec { [ name = expr ; ]… }

rec {
  x = y;
  y = x;
}.x
`infinite recursion encountered`

## Operator

String:     +
Number:     + - * /
Relation:   == !=
Boolean:    !
Attr:       a.x
            a.x or 1
Sets:       {} // {}

## expression

### Let-expressions

let-in: let [ identifier = expr; ]... in expr

let x = 1; y = 2; in x + y

### Inheriting attributes

inherit pkgs src;
inherit (pkgs) src pkg1 pkg2 pkg3;
        Adds the variables to the current scope (attribute set
        or `let` bindings).

let x = { a = 1; b = 2; }; inherit (builtins) attrNames; in { names = attrNames x; }

let x = { a = 1; b = 2; }; in { names = builtins.attrNames x; }


### With-expressions

with e1; e2
with builtins; head [ 1 2 3 ]
with (import ./def.nix); ...

let a = 3; in with { a = 1; }; let a = 4; in with { a = 2; }; a let a = 3; in with { a = 1; }; let a = 4; in with { a = 2; }; a


### Conditionals

if 1 + 1 == 2
then "yes!"
else "no!

### Assertions

assert 1+1==2;
"yes!"

{ localServer ? false , httpServer ? false , sslSupport ? false , pythonBindings ? false , javaSwigBindings ? false , javahlBindings ? false , stdenv, fetchurl , openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null }:

assert localServer -> db4 != null; ① assert httpServer -> httpd != null && httpd.expat == expat; ② assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); ③ assert pythonBindings -> swig != null && swig.pythonSupport; assert javaSwigBindings -> swig != null && swig.javaSupport; assert javahlBindings -> j2sdk != null;

stdenv.mkDerivation { name = “subversion-1.1.1”; … openssl = if sslSupport then openssl else null; ④ … }



## Functions

pattern: body


x: x + 1
x: y: x + y

(x: x + 1) 100
let inc = x: x + 1; in inc (inc (inc 100))

{ x, y }: x + y
{ x, y ? "bar" }: x + y
{ x, y, ... }: x + y
{ x, y } @ args: x + y
args @ { x, y }: x + y
args@{ x, y, z, ... }: z + y + x + args.a

### eg

let concat = x: y: x+y; f = concat “foo”; g = concat “goo”; in [(f “bar”) (f “xxx”) (g “bar”) (g “xxx”)]

let f = args@{ a ? 23, … }: [ a args ]; in f {}

let f = args @ { … }: [ (args.a or 23) args ]; in f {}



## Built-in functions

import ./foo.nix
map (x: x + x) [ 1 2 3 ]

## Comments

ccccoments

/* … */