@@ -0,0 +1,333 @@
3+subtitle: Язык, пакетный менеджер и экосистема
4+author: Александр Бантьев
12+- \usepackage[utf8]{inputenc}
13+- \usepackage[russian]{babel}
19+Nix - это чистый функциональный язык с динамическим типизированием и пакетный менеджер на основе этого языка.
21+Философия Nix как пакетного менеджера - атомарность, повторяемость и чистота сборки.
23+Как язык, Nix отличается упором на ленивые вычисления и ориентированностью на данные: большая часть кода на Nix представляет из себя напоминающие JSON множества аттрибутов (attrsets).
26+{ height=90% }
31+Рассмотрим основы синтаксиса Nix.
33+### Краткая инструкция для желающих повторить
35+$ curl https://nixos.org/nix/install | sh
40+## Числа, арифметика и комментарии
42+nix-repl> :t 4 # Показать тип выражения
44+nix-repl> 1 + 2 - 3 * 2
48+nix-repl> builtins.add 1 2
50+nix-repl> # Однострочный комментарий
51+nix-repl> /* Многострочный комментарий */
54+Арифметические операторы лучше обносить пробелами! У символов `/` и `-` есть особые значения в Nix
60+## Булевы, булева арифметика и if
64+nix-repl> true && false
66+nix-repl> true || false
68+nix-repl> if true || false then 3 else 4
70+nix-repl> if false then 5 else 6
92+## Переменные и стороковая интерполяция
94+nix-repl> foo = "hello"
95+nix-repl> "${foo}, world!"
100+Названия переменных могут содержать знак `-`
102+nix-repl> foo-bar = 10
106+Но не могут содержать не-ASCII!
109+error: syntax error, unexpected $undefined, at (string):1:1
112+## Как избежать интерполяции?
113+Довольно часто встречаются ситуации, когда мы хотим вставить в строку последовательность `${...}` (например, в bash-код).
119+nix-repl> ''test ''${foo} test''
123+## Пути (paths) и URL
130+nix-repl> ./hello # Относительно текущего .nix файла или PWD для repl
132+nix-repl> https://typeable.io
133+"https://typeable.io"
134+nix-repl> :t https://typeable.io
138+Пути, как и названия переменных, не могут содержать не-ASCII. Я бы рассматривал это, как баг.
140+nix-repl> /home/balsoft/Документы
141+error: path '/home/balsoft/' has a trailing slash
146+Списки в Nix иммутабельны и могут содержать значения любых типов вперемешку.
149+nix-repl> [ 2 "foo" true (2+3) ]
155+Обратите внимание: элементы списка не разделены запятыми!
158+error: syntax error, unexpected '+', at (string):1:5
159+nix-repl> [ (1 + 2) ]
161+nix-repl> [ import ./hello.nix {} ]
162+[ «primop-app» /home/balsoft/hello.nix { ... } ]
165+## Множества аттрибутов (attribute sets, attrsets)
167+nix-repl> s = { foo = "bar"; a-b = "baz"; "123" = "num"; }
169+{ "123" = "num"; a-b = "baz"; foo = "bar"; }
174+nix-repl> s.${toString (122 + 1)}
176+nix-repl> s.abc or "not found" # Note that `or` is a keyword
178+nix-repl> s // { a = 10; }
179+{ "123" = "num"; a = 10; a-b = "baz"; foo = "bar"; }
180+nix-repl> rec { a = 3; b = a + 4; } # Recursive attrset
187+nix-repl> let a = 3; b = 4; in a + b
189+nix-repl> let a = 4; b = a + 5; in b # Let definitions are recursive
191+nix-repl> let a = 3; a = 8; in a
192+error: attribute `a' at (string):1:12 already defined at (string):1:5
193+nix-repl> longName = { a = 3; b = 4; }
194+nix-repl> longName.a + longName.b
196+nix-repl> with longName; a + b
200+## Функции (functions)
204+nix-repl> double = x: x * 2
209+nix-repl> greet = end: name: "Hello, ${name} ${end}"
210+nix-repl> greet "dredozubov" "!"
211+"Hello, dredozubov !"
212+nix-repl> greetExclamaition = greet "!"
213+nix-repl> greetExclamaition "s9gf4ult"
219+nix-repl> greet = { name, end }: "Hello, ${name} ${end}"
220+nix-repl> greet { name = "ak3n"; exc = "!"; }
222+nix-repl> greet = { name, end ? "!" }: "Hello, ${name} ${end}"
223+nix-repl> greet { name = "ak3n"; }
225+nix-repl> greet { name = "ak3n"; end = "."; }
227+nix-repl> greet = { name, end ? "!", ... }: "Hello, ${name} ${end}"
228+nix-repl> greet { name = "ak3n"; end = "."; extra = true; }
230+nix-repl> foo = {a, ...}@args: args // { a = a + 3; }
231+nix-repl> foo { a = 10; b = 11; }
235+## Подключения файлов (import)
244+### Обратно в наш уютный repl
246+nix-repl> a = import ./number.nix
247+nix-repl> f = import ./function.nix
252+## Деривации (derivation)
254+nix-repl> d = derivation {
256+ builder = "mybuilder";
257+ system = "mysystem";
262+«derivation /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv»
265+### Лирическое отступление
266+На этом этапе нужно рассмотреть, что же представляет из себя nix-the-package-manager.
268+# Пакетный менеджер Nix
269+## Хранилище (nix store)
270+> In the beginning was the Store, and the Store was with Nix, and the Store was Nix.
275+$ ls /nix/store | wc -l
277+$ nix add-to-store nix.conf
278+/nix/store/za34q8y0jcx3qsrnbrd005mh8zcnlrlr-nix.conf
284+$ cat /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv
286+([("out","/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname","","")]
292+,[("builder","mybuilder")
294+ ,("out","/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname")
295+ ,("system","mysystem") ] )
300+text' s t = text t # fontSize (local s) <> strutY (s * 1.3)
303+sideText' s t = baselineText t # fontSize (local s)
305+box t = text' 0.2 t # fc white # font "hack" <> roundedRect 2 0.4 0.2 # fc blue
309+boxes = box "myname.nix" # named "nix"
311+ (strutY 0.5 <> sideText' 0.1 "Вычисление (nix как язык)")
313+ box "myname.drv" # named "drv"
315+ (strutY 0.5 <> sideText' 0.1 "Сборка (nix как пакетный менеджер)")
317+ box " myname " # named "out"
319+arrows = arrowBetween (0 ^& (-0.2)) (0 ^& (-0.7))
320+ <> arrowBetween (0 ^& (-1.1)) (0 ^& (-1.6))
322+example = boxes <> arrows
325+*На эту диаграмму ушло четыре с половиной часа. Ненавижу `diagrams`, `diagrams-pandoc` и `svg-fonts`*
331+https://imgur.com/0gPQ4zg