Get the code: learn.nix
Nix Àr ett enkelt funktionelt sprÄk utvecklat för Nix pakethanteraren och NixOS linuxdistributionen.
Du kan utvÀrdera Nix uttryck genom att anvÀnda
nix-instantiate
eller nix-repl.
with builtins; [
# Kommentarer
#=========================================
# Inlinekommentarer ser ut sÄhÀr.
/* Flerradskommentarer ser ut
sÄhÀr. */
# Booleaner
#=========================================
(true && false) # Och
#=> false
(true || false) # Eller
#=> true
(if 3 < 4 then "a" else "b") # Villkorlig
#=> "a"
# Heltal
#=========================================
# Heltal Àr den enda numeriska typen.
1 0 42 (-3) # NÄgra heltal
(4 + 6 + 12 - 2) # Addition
#=> 20
(7 / 2) # Division
#=> 3
# StrÀngar
#=========================================
"StrÀnglitteraler omgÀrdas av raka citationstecken."
"
StrÀnglitteraler kan strÀcka sig
över flera rader.
"
''
Detta kallas för en indenterad strÀngliteral, omgÀrdad av dubbla apostrofer
Den plockar intelligent bort ledande blanktecken.
''
''
a
b
''
#=> "a\n b"
("ab" + "cd") # StrÀngkonkatenering
#=> "abcd"
# Antikvotering lÄter dig bÀdda in sprÄkvÀrden i strÀngar.
("Din hemkatalog Àr ${getEnv "HOME"}")
#=> "Din hemkatalog Àr /home/alice"
# SökvÀgar
#=========================================
# Nix har en primitiv, inbyggd, typ för sökvÀgar.
/tmp/tutorials/learn.nix
# Relativa sökvÀgar förenas med sökvÀgen till dess definerande fils sökvÀg
# vid tolkningstillfÀllet för att skapa dess absoluta sökvÀg.
tutorials/learn.nix
#=> /the-base-path/tutorials/learn.nix
# En sökvÀg mÄste innehÄlla Ätminstonde ett snedstreck, sÄ en relativ sökvÀg
# till en fil i samma katalog mÄste ges ett "./" prefix
./learn.nix
#=> /the-base-path/learn.nix
# Divisionsoperatorn / mÄste omges av blanksteg om man vill att det skall
# tolkas som heltalsdivision
7/2 # Detta Àr en sökvÀg
(7 / 2) # Detta Àr heltalsdivision
# Importer
#=========================================
# En nix fil innehÄller ett enstaka topnivÄuttryck utan fria variabler.
# Ett importuttryck evalueras till vÀrdet pÄ filen som den importerar.
(import /tmp/foo.nix)
# Importer kan ocksÄ specificeras med hjÀlp av strÀngar.
(import "/tmp/foo.nix")
# ImportsökvÀgar mÄste vara absoluta. SökvÀgslitteraler hÀrleds vid
# tolkningstillfÀllet sÄ följande Àr ok.
(import ./foo.nix)
# Men detta Àr inte nÄgot som sker med strÀngar.
(import "./foo.nix")
#=> error: string âfoo.nixâ doesn't represent an absolute path
# Let
#=========================================
# `let` block tillÄter oss att binda vÀrden till namn.
(let x = "a"; in
x + x + x)
#=> "aaa"
# Bindingar kan referera till varandra och deras ordning sinsemellan spelar
# ingen roll.
(let y = x + "b";
x = "a"; in
y + "c")
#=> "abc"
# Innre bindningar skuggar utanpÄliggande bindingar.
(let a = 1; in
let a = 2; in
a)
#=> 2
# Funktioner
#=========================================
(n: n + 1) # En lambdafunktion som lÀgger till 1
((n: n + 1) 5) # Samma funktion applicerad pÄ 5
#=> 6
# Det finns ingen syntax för direkt namngivna funktioner, istÀllet binder man
# dessa med `let` block som andra vÀrden.
(let succ = (n: n + 1); in succ 5)
#=> 6
# En funktion Àr en lambda med en parameter. Flera parameterar kan ges med
# hjÀlp av currying.
((x: y: x + "-" + y) "a" "b")
#=> "a-b"
# Vi kan ocksÄ ha namngivna funktionsparametrar, vilket vi kommer komma till
# senare, efter att vi introducerat attributset.
# Listor
#=========================================
# Listor noteras med hakparenteser.
(length [1 2 3 "x"])
#=> 4
([1 2 3] ++ [4 5])
#=> [1 2 3 4 5]
(concatLists [[1 2] [3 4] [5]])
#=> [1 2 3 4 5]
(head [1 2 3])
#=> 1
(tail [1 2 3])
#=> [2 3]
(elemAt ["a" "b" "c" "d"] 2)
#=> "c"
(elem 2 [1 2 3])
#=> true
(elem 5 [1 2 3])
#=> false
(filter (n: n < 3) [1 2 3 4])
#=> [ 1 2 ]
# MĂ€ngder
#=========================================
# Ett attributset Àr en oordnad mappning av strÀngnycklar och vÀrden.
{ foo = [1 2]; bar = "x"; }
# Punktoperatorn . vÀljer ett vÀrde frÄn attributset:et
{ a = 1; b = 2; }.a
#=> 1
# FrÄgeoperatorn ? testar om en nyckel Àr nÀrvarande i ett attributset
({ a = 1; b = 2; } ? a)
#=> true
({ a = 1; b = 2; } ? c)
#=> false
# Snedstrecksoperatorn // slÄr ihop tvÄ attributset:ar.
({ a = 1; } // { b = 2; })
#=> { a = 1; b = 2; }
# VÀrden pÄ höger skriver över vÀrden till vÀnster.
({ a = 1; b = 2; } // { a = 3; c = 4; })
#=> { a = 3; b = 2; c = 4; }
# Recursionsnyckelordet rec noterar ett rekursivt attributset (en fixpunkt)
# i vilket attributen kan referera till varandra.
(let a = 1; in { a = 2; b = a; }.b)
#=> 1
(let a = 1; in rec { a = 2; b = a; }.b)
#=> 2
# NÀstlade attributset:ar kan definieras bit för bit.
{
a.b = 1;
a.c.d = 2;
a.c.e = 3;
}.a.c
#=> { d = 2; e = 3; }
# Ett attributsets barn kan inte tilldelas pÄ detta vis om attributsetet
# sjÀlvt blivit direkt tilldelat.
{
a = { b = 1; };
a.c = 2;
}
#=> error: attribute âaâ already defined
# Bindningsintroduktion, `with`
#=========================================
# Det attributset vilket Äterfinns i ett `with` uttryck kommer fÄ sina
# vÀrdebindningar introducerade i efterkommande uttryck.
(with { a = 1; b = 2; };
a + b)
# => 3
# Innre bindningar skuggar yttre bindningar.
(with { a = 1; b = 2; };
(with { a = 5; };
a + b))
#=> 7
# Första raden av detta exempel börjar med "with builtins;" eftersom builtins
# Àr ett attributset innehÄllande alla inbyggda hjÀlpfunktioner sÄsom
# (length, head, tail, filter, etc.). Detta sparar oss frÄn att hela tiden
# referera in i det attributset:et , alltsÄ du kan anvÀnda bara "length"
# istÀllet för "builtins.length".
# Attributsetmönster
#=========================================
# Attributset Àr anvÀndbara nÀr vi skall skicka med flera vÀrden till en
# funktion.
(args: args.x + "-" + args.y) { x = "a"; y = "b"; }
#=> "a-b"
# Man kan anvÀnda attributsetmönster för ökad tydlighet.
({x, y}: x + "-" + y) { x = "a"; y = "b"; }
#=> "a-b"
# Attributmönster misslyckas dock om det medskickade attributmönstret
# innehÄller extra nycklar.
({x, y}: x + "-" + y) { x = "a"; y = "b"; z = "c"; }
#=> error: anonymous function called with unexpected argument âzâ
# Genom att lÀgga till ", ..." kan vi ignorera ytterliggare nycklar.
({x, y, ...}: x + "-" + y) { x = "a"; y = "b"; z = "c"; }
#=> "a-b"
# Felmeddelanden
#=========================================
# `throw` gör att programtolken gör abort med dess tillhörande felmeddelande
causes evaluation to abort with an error message.
(2 + (throw "foo"))
#=> error: foo
# `tryEval` fÄngar kastade fel `throw`.
(tryEval 42)
#=> { success = true; value = 42; }
(tryEval (2 + (throw "foo")))
#=> { success = false; value = false; }
# `abort` fungerar som `throw`, men Àr kritiskt och kan inte fÄngas.
(tryEval (abort "foo"))
#=> error: evaluation aborted with the following error message: âfooâ
# `assert` utvÀrderas till det givna vÀrdet om dess predikat Àr sant.
# annars skickar den ett fÄngbart fel.
(assert 1 < 2; 42)
#=> 42
(assert 1 > 2; 42)
#=> error: assertion failed at (string):1:1
(tryEval (assert 1 > 2; 42))
#=> { success = false; value = false; }
# Orenhet
#=========================================
# Eftersom repeterbarhet för byggen Àr en kritisk egenskap för
# Nix-pakethanteraren betonas funktionell renhet i Nix-programmeringssprÄket.
# Men med det sagt existerar det kÀllor till orenhet
# Man kan referera till miljövariabler.
(getEnv "HOME")
#=> "/home/alice"
# `trace` funktionen anvÀnds för att debugga. Den skriver ut första argumentet
# till stderr och reduceras samtidigt till det andra argumentet.
(trace 1 2)
#=> trace: 1
#=> 2
# Man kan skriva filer till Nix-store, lagringsplatsen för alla Nix-uttryck.
# Ăven om detta Ă€r orent beteende Ă€r det hyfsat sĂ€kert eftersom filens
# lagringsplats Àr hÀrledd frÄn dess innehÄll och beroenden. Man kan lÀsa
# filer frÄn precis överallt. I nedanstÄende exempel skriver vi en fil till
# Nix-store och sedan lÀser tillbaka den.
(let filename = toFile "foo.txt" "hello!"; in
[filename (builtins.readFile filename)])
#=> [ "/nix/store/ayh05aay2anx135prqp0cy34h891247x-foo.txt" "hello!" ]
# Vi kan ocksÄ ladda ned filer till Nix-store.
(fetchurl "https://example.com/package-1.2.3.tgz")
#=> "/nix/store/2drvlh8r57f19s9il42zg89rdr33m2rm-package-1.2.3.tgz"
]
Got a suggestion? A correction, perhaps? Open an Issue on the GitHub Repo, or make a pull request yourself!
Originally contributed by Chris Martin, and updated by 2 contributors.