-
Notifications
You must be signed in to change notification settings - Fork 4
Nix Tutorial 2 : Data Types & Language Constructs
This guide introduces the types of data in Nix and the main language features, with simple explanations, icons, and real examples for newcomers.
Every value in Nix has a type. Knowing these types helps you write correct and maintainable Nix expressions.
-
Description: Signed 64-bit numbers, e.g.,
123,-42 -
Example:
let a = 5; b = -3; in a + b # Result: 2
-
Check type:
builtins.isInt a→true
-
Description: 64-bit floating-point numbers, e.g.,
1.5,-0.02,.1e5 -
Example:
let pi = 3.1415; in pi * 2 # Result: 6.283
-
Check type:
builtins.isFloat pi→true
-
Description: Only two values:
trueorfalse -
Example:
let flag = true; in if flag then "Yes" else "No" # Result: "Yes"
-
Check type:
builtins.isBool flag→true
-
Description: Immutable sequence of bytes (not characters!); written with double quotes
"foo"or indented strings''foo'' -
Example:
let msg = "Hello, Nix!"; in msg
let multi = '' Line 1 Line 2 ''; in multi
-
Check type:
builtins.isString msg→true
-
Description: POSIX-style file paths (e.g.,
./file.txt,/etc/hosts). Paths and strings are not the same. -
Example:
let f = ./file.txt; # relative path g = /etc/hosts; # absolute path in f
-
Check type:
builtins.isPath f→true
Note:
Paths are resolved relative to their base directory.
"./foo.txt" (as a string) is different from ./foo.txt (as a path).
-
Description: The single value
null(like "nothing" or "None" in other languages) -
Example:
let val = null; in if val == null then "empty" else "not empty"
-
Check type:
val == null→true
-
Description: Key-value pairs, like dictionaries or objects in other languages.
-
Example:
let person = { name = "Alice"; age = 30; }; in person.name # Result: "Alice"
-
Check type:
builtins.isAttrs person→true
Access keys: set.key
Nested sets: { a = { b = 2; }; } → access with .a.b
-
Description: Ordered collections (arrays) of values, in square brackets.
-
Example:
let xs = [ 1 2 3 ]; in builtins.length xs # Result: 3
-
Check type:
builtins.isList xs→true
Access elements: builtins.elemAt xs 0 → 1
-
Description: Functions are first-class in Nix. You can pass them around, store them, and call them.
-
Example:
let inc = x: x + 1; in inc 4 # Result: 5
let add = { x, y }: x + y; in add { x = 2; y = 3; } # Result: 5
-
Check type:
builtins.isFunction inc→true
- Description: Opaque values created by plugins. Usually not used in everyday Nix code.
- Example: Not commonly encountered for new users.
-
String context is metadata that tracks where a string came from (for reproducibility).
-
You don’t need to deal with string context directly.
-
Checking context:
builtins.hasContext "hello" # false
builtins.getContext (builtins.storePath "/nix/store/xyz-foo")
-
Clearing context:
builtins.unsafeDiscardStringContext someString
-
Most users never need to touch this—just know it exists!
-
String:
"hello",''multi-line'' -
Number:
42,1.2,-7 -
Path:
./foo.txt,/etc/passwd -
List:
[ 1 2 3 ] -
Attribute set:
{ key = "val"; }
-
Define:
{ a = 1; b = "foo"; }
-
Access:
{ a = 1; } .a # 1
-
Default value:
{ a = 1; } .b or 42 # 42
-
Complex keys:
{ "foo bar" = 123; }."foo bar" # 123
-
Allow self-reference among keys:
rec { x = y; y = 10; }.x # Result: 10
-
Define local variables:
let a = 1; b = 2; in a + b # 3
-
Copy from scope or other set:
let x = 5; in { inherit x; y = 3; } # { x = 5; y = 3; }
let set = { a = 1; b = 2; }; in { inherit (set) a; } # { a = 1; }
-
Anonymous function:
x: x * 2
-
Function with attribute set as argument:
{ a, b }: a + b
-
Default value for function argument:
{ x, y ? 5 }: x + y
( { x, y ? 2 }: x * y ) { x = 3; } # 6
-
If-else:
if true then "yes" else "no"
-
Check conditions, fail early if not met:
assert 1 < 2; "ok" # "ok" assert false; "fail" # Error!
-
Bring all attributes into scope:
let as = { x = 1; y = 2; }; in with as; x + y # 3
-
Single line:
# Comment -
Multi-line:
/* Block comment */
-
Normal:
"Hello, Nix!" -
Indented/multi-line:
'' First line Second line ''
- Start with a letter or
_. - Can contain letters, digits,
_,',-. - Some words are reserved (like
let,if,else).
-
Insert variables or expressions into strings with
${...} -
Example:
let name = "world"; in "Hello, ${name}!" # "Hello, world!"
-
In attribute names:
let key = "foo"; in { ${key} = 123; } # { foo = 123; }
Arithmetic: +, -, *, /
Comparison: <, >, ==, !=, <=, >=
Logical: &&, ||, !, -> (implication)
Update sets: //
String concat: +
List concat: ++
Path concat: +
-
Example:
( { a = 1; } // { b = 2; } ) # { a = 1; b = 2; } [ 1 2 ] ++ [ 3 4 ] # [ 1 2 3 4 ]
| Type | Example | Check Type |
|---|---|---|
| Integer | 123 |
builtins.isInt 123 |
| Float | 3.14 |
builtins.isFloat 3.14 |
| Boolean | true |
builtins.isBool true |
| String | "foo" |
builtins.isString "foo" |
| Path | ./file.txt |
builtins.isPath ./file.txt |
| Null | null |
val == null |
| Attribute Set | { a = 1; } |
builtins.isAttrs {} |
| List | [ 1 2 3 ] |
builtins.isList [1] |
| Function | x: x + 1 |
builtins.isFunction (x: x) |
| External | Plugin-defined | N/A |
Bernard Sibanda is a global Technology Entrepreneur, Web3 and Software Consultant with a deep focus on Cardano Blockchain, Midnight and Community building.
Key Positions:
- Founder, CTO, Developer Advocate cohort #1, Fullstake Developer, Cardano Ambassador, Catalyst Project Manager, DREP-WIMS:
- Co-founder of ABL Tech and Cardano Africa Live
- EBU-certified Plutus Pioneer (Plutus/Haskell)
- Cohort #1 Plutus Pioneer Developer
- Catalyst Community Reviewer & Funded Projects Manager
-
DRep for WIMS-Cardano (ID:
drep1yguj8zu48n99pv70yl6ckzt9hdgjy8yjnlqs2uyzcpafnjgu4vkul) - Intersect Developer Advocate
- Intersect Committe Member 2025-2026
- Cardano Marketer,Promoter and blogger
- Cardano Open Source Contributor
- Cardano communities and events organizer and builder
- Cardano Ambassador for South Africa
Official links:
- Stablecoins Dex
- Coxygen Global Universities
- WIMS Cardano Global
- Cardano Africa Live
- WIMS Cardano Videos
- Cardano Smart Contract Videos
- Fullstack IT Consulting
Social links: