1
0
mirror of https://github.com/adambard/learnxinyminutes-docs.git synced 2025-08-31 18:32:22 +02:00

Simplify language codes in directories

This commit is contained in:
Boris Verkhovskiy
2024-12-08 20:29:09 -07:00
parent 3da692272f
commit 912da583da
489 changed files with 0 additions and 0 deletions

86
sv/bf.md Normal file
View File

@@ -0,0 +1,86 @@
---
language: BF
filename: brainfuck-sv.bf
contributors:
- ["Prajit Ramachandran", "http://prajitr.github.io/"]
- ["Mathias Bynens", "http://mathiasbynens.be/"]
translators:
- ["Richard Lindberg", "https://github.com/Lidenburg"]
lang: sv-se
---
Brainfuck (ej versaliserat förutom vid ny mening) är ett extremt
minimalistiskt Turing-komplett programmeringsspråk med endast 8 kommandon.
Du kan testa brainfuck i din webbläsare via [brainfuck-visualizer](http://fatiherikli.github.io/brainfuck-visualizer/).
```bf
Alla karaktärer förutom "><+-.,[]" (inte inkluderat citattecken) ignoreras.
Brainfuck är representerat av ett fält med 30 000 celler initialiserade till
noll och en data pekare som pekar på den valda cellen.
Det finns åtta kommandon:
+ : Ökar värdet av den valda cellen med ett.
- : Minskar värdet av den valda cellen med ett.
> : Flyttar data pekaren till nästa cell (cellen till höger).
< : Flyttar data pekaren till förra cellen (cellen till vänster).
. : Skriver ut ASCII värdet av den valda cellen (t.ex. 65 = 'A').
, : Läser in en karaktär till den valda cellen.
[ : Om värdet vid den valda cellen är noll, hoppa till matchande ].
Annars fortsätts till nästa instruktion.
] : Om värdet vid den valda cellen är noll, fortsätt till nästa instruktion.
Annars, gå tillbaka till matchande ].
[ och ] formar en while loop.
Nedan är ett exempel på ett simpelt brainfuck program.
++++++ [ > ++++++++++ < - ] > +++++ .
Programmet skriver ut bokstaven 'A'. Först ökar den värdet av cell #1 till 6.
Cell #1 kommer att användas för att loopa. Sen börjar den loopen (vid '[') och
flyttar till cell #2. Den ökar värdet av cell #2 10 gånger, går tillbaka till
cell #1 och minskar den med 1. Den gör det här 6 gånger (så många iterationer
det tar för cell #1 att bli noll).
Nu är programmet på cell #1, vilket har ett värde av 0 och cell #2 har värdet 60.
Programmet flyttar pekaren till cell #2 och ökar värdet med 5, vilket leder till
att cell #2 har ett värde av 65 (vilket är bokstaven 'A' i ASCII), sedan skriver
den ut cell #2 och bokstaven 'A' skrivs ut till skärmen.
, [ > + < - ] > .
Det här programmet läser en karaktär från användaren och kopierar karaktären
till cell #1. Sedan startas en loop. Pekaren flyttas till cell #2, värder ökas
med ett, pekaren flyttas tillbaka till cell #1 och minskar värdet med ett.
Det här fortsätter tills cell #1 innehåller noll och cell #2 innehåller det
värde som cell #1 innehöll från början. Eftersom att programmet vid slutet av
loopen är på cell #1 flyttas pekaren till cell #2 och sedan skriver den ut
värdet av cell #2 i ASCII.
Värt att komma ihåg är att programmet ovan kan skrivas utan mellanslag också:
,[>+<-]>.
Försök och lista ut vad det här programmet gör:
,>,< [ > [ >+ >+ << -] >> [- << + >>] <<< -] >>
Programmet tar två nummer som indata, och multiplicerar dem.
Kärnan av det är att den först läser in två tal/bokstäver. Sedan startar
den yttre loopen som beror på cell #1. Sedan går den vidare till cell #2 och
startar den innre loopen som beror på cell #2 och ökar cell #3. Men det uppstår
ett problem: Vid slutet av den innre loopen är cell #2 noll. Vilket betyder att
den inre loopen inte kommer att fungera tills nästa gång. För att lösa det här
problemet ökas också cell #4 som sedan kopieras till cell #2.
Sedan är resultatet i cell #3.
```
Och det är brainfuck. Inte så svårt va? För skojs skull kan du skriva dina egna
brainfuck program, eller skriva en egen brainfuck interpretator i ett annat
språk. interpretatorn är ganska simpel att implementera, men om man är en
masochist, testa att skriva en brainfuck interpretator… i brainfuck.

460
sv/haskell.md Normal file
View File

@@ -0,0 +1,460 @@
---
language: Haskell
filename: learnhaskell-sv.hs
contributors:
- ["Adit Bhargava", "http://adit.io"]
translators:
- ["Edward Tjörnhammar", "http://edwtjo.me"]
lang: sv-se
---
Haskell skapades för att vara ett praktiskt, rent, funktionellt
programmeringsspråk. Det är känt för sin använding av monader och dess
härledande typsystem men anledningen till att jag ständigt återbesöker språket
är på grund av dess elegans. Haskell gör programmering till ett rent nöje.
```haskell
-- Radkommenterar börjar med två bindestreck.
{- Flerradskommentarer innesluts av vänster/höger måsvinge bindestreck
block på detta vis.
-}
----------------------------------------------------
-- 1. Fördefinierade datatyper och operatorer
----------------------------------------------------
-- Du har siffror
3 -- 3
-- Matte fungerar som förväntat
1 + 1 -- 2
8 - 1 -- 7
10 * 2 -- 20
35 / 5 -- 7.0
-- Division är normalt inte heltalsdivision
35 / 4 -- 8.75
-- Heltalsdivision, här infix div
35 `div` 4 -- 8
-- Boolar (Sant och Falskt) är fördefinierade
True
False
-- Samt dess operationer
not True -- False
not False -- True
1 == 1 -- True
1 /= 1 -- False
1 < 10 -- True
-- I ovanstående exempel är `not` en funktion vilken bara tar ett argument.
-- Haskell behöver inte paranteser för sina funktionsanrop... alla argument
-- ges mellanslagsseparerade direkt efter funktionen. Det övergripande mönstret
-- är:
-- func arg1 arg2 arg3...
-- Se sektionen om funktioner för information om hur du skriver dina egna.
-- Strängar och bokstäver
"Detta är en sträng"
'a' -- bokstav
'Du kan inte använda enkelfnutt för strängar.' -- fel!
-- Strängar kan konkateneras
"Hej " ++ "världen!" -- "Hej världen!"
-- En sträng är en lista av bokstäver
['H', 'e', 'j', 's', 'a', 'n'] -- "Hejsan"
"Detta är en sträng" !! 0 -- 'D'
----------------------------------------------------
-- 2. Listor och Tupler
----------------------------------------------------
-- Varje element i en lista måste ha samma typ.
-- Dessa listor är ekvivalenta:
[1, 2, 3, 4, 5]
[1..5]
-- Intervall är mångsidiga.
['A'..'F'] -- "ABCDEF"
-- Man kan stega intervall.
[0,2..10] -- [0, 2, 4, 6, 8, 10]
[5..1] -- [] (Haskell förutsätter normalt inkrement)
[5,4..1] -- [5, 4, 3, 2, 1]
-- Indexering in i en lista
[1..10] !! 3 -- 4 (nollindexerat)
-- Man kan ha oändliga listor i Haskell!
[1..] -- listan över alla naturliga tal
-- Oändliga listor fungerar enbart för att Haskell har "lat evaluering".
-- Det betyder att Haskell bara evaluerar de uttryck den måste. Du kan alltså
-- fråga efter det 1000:e elementet i en oändlig lista och Haskell kommer då ge
-- dig det:
[1..] !! 999 -- 1000
-- Nu har Haskell evaluerat element 1 till 1000 i denna lista... men resten
-- av medlemmarna i denna oändliga lista existerar inte ännu! Haskell kommer
-- faktiskt inte utvärdera element den inte måste.
-- Sammanslagning av två listor
[1..5] ++ [6..10]
-- Lägg till 0 vid listhuvudet
0:[1..5] -- [0, 1, 2, 3, 4, 5]
-- fler listoperationer som huvud, svans, initiella samt sista
head [1..5] -- 1
tail [1..5] -- [2, 3, 4, 5]
init [1..5] -- [1, 2, 3, 4]
last [1..5] -- 5
-- listomfattningar
[x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10]
-- med bivilkor
[x*2 | x <- [1..5], x*2 > 4] -- [6, 8, 10]
-- Varje element i en tupel kan ha olika typ men en tupel kan bara ha en
-- fixerad, eller statisk, längd.
-- En tupel:
("haskell", 1)
-- För att komma åt element i ett par, alltså en 2-tupel, finns
-- de fördefinierade funktionerna:
fst ("haskell", 1) -- "haskell"
snd ("haskell", 1) -- 1
----------------------------------------------------
-- 3. Funktioner
----------------------------------------------------
-- En enkel funktion med två parametrar
add a b = a + b
-- Notera även att om du använder ghci (Haskellinterpretatorn) kommer du behöva
-- använda `let` namnbindning för att synliggöra din funktionsdeklaration,
-- alltså
let add a b = a + b
-- För att använda funktionen
add 1 2 -- 3
-- Man kan även göra funktionsanropet infix, alltså mellan parametersättningen,
-- med hjälp av bakåtfnuttar:
1 `add` 2 -- 3
-- Du kan även definiera funktioner vars funktionsnamn avsaknar bokstäver!
-- Med hjälp av parenteser kan du därmed definiera operatorer (normalt infix)!
-- Följande är en operator för heltalsdivision, vilken förlitar sig på div:
(//) a b = a `div` b
35 // 4 -- 8
-- Funktionsvakter: ett enkelt sätt att grena ut dina funktioner
fib x
| x < 2 = 1
| otherwise = fib (x - 1) + fib (x - 2)
-- Mönstermatchning fungerar på liknande vis. Här ger vi tre olika
-- parametermatchningar för vårat fib-resulat. Haskell kommer automatiskt följa
-- första bästa träff, uppifrån ned, vars vänstra sida om likhetstecknet matchar
-- anroparens parametervärde.
fib 1 = 1
fib 2 = 2
fib x = fib (x - 1) + fib (x - 2)
-- Mönstermatchning på tupler:
foo (x, y) = (x + 1, y + 2)
-- Mönstermatchning på listor. Här är `x` det första elementet i listan och `xs`
-- är resten av listan. Nu kan vi skriva våran egen map-funktion
minMap func [] = []
minMap func (x:xs) = func x:(minMap func xs)
-- Anonyma funktioner, eller lambdauttryck, skapas med hjälp av omvänt
-- snedstreck, följt av parametrarna
minMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7]
-- Användning av fold (även kallad `inject`, `reduce`, osv.) tillsammans med en
-- anonym funktion. `fold1` är en vänstervikande funktion och använder första
-- värdet i listan som det initiella värdet för ackumulatorn.
foldl1 (\acc x -> acc + x) [1..5] -- 15
----------------------------------------------------
-- 4. Mer funktioner
----------------------------------------------------
-- Partiell applikation:
-- Om du inte anropar funktionen med alla sina argument
-- blir den partiellt applicerad. Det betyder att du erhåller en funktion där en
-- delmängd av parametrarna blivit värdesatta men några är fortfarande fria.
add a b = a + b
foo = add 10 -- foo är nu en funktion som tar ett nummer och lägger till 10 till
-- det
foo 5 -- 15
-- Ett annat sätt att skriva samma sak
foo = (10+)
foo 5 -- 15
-- Funktionskomposition:
-- Operatorn `.` kedjar ihop funktioner
-- Till exempel, nedan är `foo` en funktion som tar ett värde, den adderar 10
-- till det, multiplicerar det resultatet med 4 och sen ersätts med det värdet.
foo = (4*) . (10+)
-- 4*(10+5) = 60
foo 5 -- 60
-- Precedensordning:
-- Haskell har en operator `$`. Denna operator applicerar en funktion till en
-- given parameter med dess precedens. I kontrast mot vanlig
-- funktionsapplikation, vilket har den högsta utvärderingsprioriteten 10 och
-- associerar till vänster, har denna prioritetsordning 0 och är
-- högerassociativ. Denna låga prioritet medför att parameteruttrycket till
-- höger om operatorn får det reducerat innan det appliceras till sin vänster.
-- före
even (fib 7) -- falskt
-- ekvivalent
even $ fib 7 -- falskt
-- med funktionskomposition
even . fib $ 7 -- falskt
----------------------------------------------------
-- 5. Typsignaturer
----------------------------------------------------
-- Haskell har ett väldigt starkt typsystem, alla giltiga uttryck har en typ.
-- Några grundläggande typer:
5 :: Integer
"hello" :: String
True :: Bool
-- Funktioner har också typer,
-- `not` tar en bool och returnerar en bool:
-- not :: Bool -> Bool
-- Här är ett exempel på en funktionssignatur vilken beskriver en funktion som
-- reducerar två heltal till ett:
-- add :: Integer -> Integer -> Integer
-- Trots att Haskell härleder typen på icke typsatta uttryck är det bra form att
-- explicit ange dessa för ens deklarerade funktioner:
double :: Integer -> Integer
double x = x * 2
----------------------------------------------------
-- 6. Kontrollflöde och Ifsatser
----------------------------------------------------
-- if-sats
haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome"
-- if-statser kan spridas över rader men indentering har betydelse
haskell = if 1 == 1
then "awesome"
else "awful"
-- case uttryck: följande är ett exempel på kommandoradsparsning
case args of
"help" -> printHelp
"start" -> startProgram
_ -> putStrLn "bad args"
-- Haskell har inte loopar istället används recursion.
-- map applicerar en funktion över varje element i en lista
map (*2) [1..5] -- [2, 4, 6, 8, 10]
-- man kan deklarera en for funktion genom att använda map
for array func = map func array
-- och därefter använda den tillsammans med en anonym funktion för att
-- efterlikna en loop
for [0..5] $ \i -> show i
-- men vi kunde även ha skrivit på följande vis:
for [0..5] show
-- Du kan använda foldl eller foldr för att reducera en lista
-- foldl <fn> <initial value> <list>
foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43
-- Vilket är samma sak som
(2 * (2 * (2 * 4 + 1) + 2) + 3)
-- foldl viker från vänster, foldr från höger
foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16
-- Vilket alltså är samma sak som
(2 * 1 + (2 * 2 + (2 * 3 + 4)))
----------------------------------------------------
-- 7. Datatyper
----------------------------------------------------
-- Såhär definierar du din egen datatyp i Haskell
data Color = Red | Blue | Green
-- När du gjort det kan du använda den i funktionssignaturer och uttryck
say :: Color -> String
say Red = "Du är Rö!"
say Blue = "Du är Blå!"
say Green = "Du är Grön!"
-- Dina datatyper kan även ta parametrar
data Maybe a = Nothing | Just a
-- Följande uttryck är alla specialiseringar av typen Maybe
Just "hello" -- har typen `Maybe String`
Just 1 -- har typen `Maybe Int`
Nothing -- har typen `Maybe a` för alla `a`
----------------------------------------------------
-- 8. Haskell IO
----------------------------------------------------
-- Även om IO inte kan förstås fullt ut utan att först förklara monader är det
-- inte svårt att lära sig tillräckligt för att komma igång
-- När ett Haskellprogram körs är det topnivåns main som körs. Main måste
-- returnerna ett värde av typen `IO a`, för någon typ `a`. Till exempel:
main :: IO ()
main = putStrLn $ "Hej, himmelen! " ++ (say Blue)
-- putStrLn har typen type String -> IO ()
-- Det är enkelt att göra IO om du kan implementera ditt program som en funktion
-- från String till String. Funktionen
-- interact :: (String -> String) -> IO ()
-- tar denna funktion och matar den med strängdata från stdin och skriver ut
-- resultatet som en sträng på stdout
countLines :: String -> String
countLines = show . length . lines
main' = interact countLines
-- Du kan tänka på värden av typen `IO ()` som att representera
-- händelsesekvenser du vill att din dator skall utföra, likt imperativa språk.
-- För att kedja ihop händelsesekvenser använder man ett syntaktiskt socker
-- kallat do-notation. Som exempel:
sägHej :: IO ()
sägHej = do
putStrLn "Vad heter du?"
namn <- getLine -- denna raden läser en rad från stdin och vi binder den till
-- funktionsnamnet `namn`
putStrLn $ "Hejsan, " ++ namn
-- Övning: Skriv din egen version av interageringsfunktionen `interact` som bara
-- läser en rad från stdin, vanliga `interact` läser till EOF.
-- Koden i sägHej kommer dock aldrig exekveras. Den enda handlingen som blir det
-- är som bekant utvärderingen av `main`.
-- För att köra `sägHej` kommentera ut definition av `main` ovan och
-- avkommentera nedanstående version:
-- main = sayHello
-- Låt oss bättre förstå hur funktionen `getLine` vi just använde fungerar. Dess
-- typsignatur är:
-- getLine :: IO String
-- Du kan tänka på typen `IO a` som att representeras av ett datorprogram vilken
-- kommer generera ett värde av typen `a` när det exekveras (utöver allt annat
-- det kan tänkas göra). Vi kan därtill binda detta värde till ett namn för
-- återanvändning genom att använda `<-`. Vi kan även skapa våran egen handling
-- av typen `IO String`:
handling :: IO String
handling = do
putStrLn "Detta är en rad, tihi"
input1 <- getLine
input2 <- getLine
-- Typen av hela `do` blocket är vad som står på sista raden. Här är även
-- `return` inte ett nyckelord i språket utan en funktion med en typsignatur
return (input1 ++ "\n" ++ input2) -- return :: String -> IO String
-- Vi kan använda `return` på samma sätt som vi använde `getLine`:
main'' = do
putStrLn "Jag kommer eka två rader!"
result <- handling
putStrLn result
putStrLn "Tack och hej leverpastej!"
-- Typen `IO` är ett exempel på en monad. Sättet Haskell utnyttjar monader på är
-- anledningen till hur språket kan bibehålla sin renhet. En funktion vilken
-- interagerar med omvärlden (alltså gör IO) blir markerad med `IO` i sin
-- typsignatur. Detta låter oss enkelt upptäcka vilka funktioner som är "rena"
-- (inte interagerar med omvärlden eller är tillståndsoberoende) and vilka
-- funktioner som inte är det.
-- Detta är ett mäktigt särdrag eftersom det är enkelt att köra rena funktioner
-- sammanlöpande; Samtidig programmering är enkel att göra i Haskell.
----------------------------------------------------
-- 9. Haskell REPL (kodtolk)
----------------------------------------------------
-- Efter installation av GHC kan vi starta tolken genom att skriva `ghci`.
-- Nu kan du mata in Haskellkod direkt i den. Nya värden måste introduceras med
-- `let` bindning:
let foo = 5
-- Du kan även se typen av namnbindningen med `:t`
> :t foo
foo :: Integer
-- Operatorer, som `+`, `:` och `$` är funktioner. Deras typ kan inspekteras
-- genom att skriva operatorn mellan parenteser:
> :t (:)
(:) :: a -> [a] -> [a]
-- Du kan få ytterliggare information om något namn genom att använda `:i`
> :i (+)
class Num a where
(+) :: a -> a -> a
...
-- Defined in GHC.Num
infixl 6 +
-- Du kan även köra alla handlingar av typen `IO ()` direkt i tolken
> sägHej
Vad är ditt namn?
Kompis!
Hello, Kompis!
```
Det finns mycket mer att upptäcka med Haskell, inklusive typklasser och monader.
Vilka är de stora idéerna som gör Haskell till det roliga programmeringsspråket
det är. Jag lämar dig med ett sista exempel; En implementation av quicksort:
```haskell
qsort [] = []
qsort (p:xs) = qsort mindre ++ [p] ++ qsort större
where mindre = filter (< p) xs
större = filter (>= p) xs
```
Det finns två populära sätt att installera Haskell på: Den traditionella [Cabal sättet](http://www.haskell.org/platform/), eller det nyare [Stack sättet](https://www.stackage.org/install).
Du kan finna vänligare och/eller djupare introduktioner till Haskell på engelska
från:
[Learn you a Haskell](http://learnyouahaskell.com/),
[Happy Learn Haskell Tutorial](http://www.happylearnhaskelltutorial.com/) eller
[Real World Haskell](http://book.realworldhaskell.org/).

84
sv/json.md Normal file
View File

@@ -0,0 +1,84 @@
---
language: JSON
filename: learnjson-sv.json
contributors:
- ["Anna Harren", "https://github.com/iirelu"]
- ["Marco Scannadinari", "https://github.com/marcoms"]
- ["himanshu", "https://github.com/himanshu81494"]
- ["Michael Neth", "https://github.com/infernocloud"]
translators:
- ["Lari Kovanen", "https://github.com/larkov"]
- ["Joakim Lahtinen", "https://github.com/VibyJocke"]
lang: sv-se
---
JSON är ett extremt enkelt datautbytesformat. Som [json.org](http://json.org) beskriver så är det lätt för människor att läsa och skriva, och för datorer att tolka och generera.
En bit av JSON måste representera antingen:
* En samling av namn/värde-par (`{ }`). I olika språk kan denna realiseras som ett objekt, struct, dictionary, hash-tabell, nyckellista eller en associativ array.
* En ordnad lista av värden (`[ ]`). I olika språk kan denna realiseras som en array, vektor, lista eller sekvens.
JSON i dess renaste form har inga kommentarer, men de flesta tolkarna accepterar C-stils (`//`, `/* */`) kommentarer. Vissa tolkar tolererar även komman efter sista elementet i en array, eller det sista attributet av ett objekt, men dessa bör undvikas för bättre kompabilitet.
Detta dokument kommer dock att tillämpa 100% giltigt JSON. Lyckligtvis så är resten av dokumentet självförklarande.
Följande datatyper stöds:
* Strängar: `"hello"`, `"\"A quote.\""`, `"\u0abe"`, `"Newline.\n"`
* Nummer: `23`, `0.11`, `12e10`, `3.141e-10`, `1.23e+4`
* Objekt: `{ "key": "value" }`
* Arrayer: `["Values"]`
* Övriga: `true`, `false`, `null`
```json
{
"nyckel": "värde",
"nycklar": "måste alltid omslutas med dubbla citationstecken",
"nummer": 0,
"strängar": "Alla unicode-tecken (inklusive \"escaping\") är tillåtna.",
"boolska värden?": true,
"nullvärden": null,
"stora tal": 1.2e+100,
"objekt": {
"kommentar": "De flesta datastukturerna i JSON kommer i form av objekt.",
"matris": [0, 1, 2, 3, "Matriser kan innehålla vad som helst.", 5],
"ytterligare objekt": {
"kommentar": "Objekten kan vara nästlade."
}
},
"trams": [
{
"kaliumkällor": ["bananer"]
},
[
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, "neo"],
[0, 0, 0, 1]
]
],
"alternativ formatering": {
"kommentar": "kolla på detta!"
, "kommats position": "spelar ingen roll - så länge det kommer innan värdet"
, "en kommentar till": "vad fint"
},
"blanksteg": "Spelar ingen roll.",
"det var kort": "Nu är du klar och kan allt vad JSON har att erbjuda."
}
```
## Fortsatt läsning
* [JSON.org](http://json.org/json-sv.html) Allt du kan tänkas vilja veta om JSON, och lite därtill.

365
sv/nix.md Normal file
View File

@@ -0,0 +1,365 @@
---
language: Nix
filename: learn-sv.nix
contributors:
- ["Chris Martin", "http://chris-martin.org/"]
translators:
- ["Edward Tjörnhammar", "http://edwtjo.me"]
lang: sv-se
---
Nix är ett enkelt funktionelt språk utvecklat för
[Nix pakethanteraren](https://nixos.org/nix/) och
[NixOS](https://nixos.org/) linuxdistributionen.
Du kan utvärdera Nix uttryck genom att använda
[nix-instantiate](https://nixos.org/nix/manual/#sec-nix-instantiate)
eller [`nix-repl`](https://github.com/edolstra/nix-repl).
```nix
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"
]
```
### Vidare Läsning (eng)
* [Nix Manual - Nix expression language](https://nixos.org/nix/manual/#ch-expression-language)
* [James Fisher - Nix by example - Part 1: The Nix expression language](https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55)
* [Susan Potter - Nix Cookbook - Nix By Example](https://ops.functionalalgebra.com/nix-by-example/)
* [Zero to Nix - Nix Tutorial](https://zero-to-nix.com/)
* [Rommel Martinez - A Gentle Introduction to the Nix Family](https://web.archive.org/web/20210121042658/https://ebzzry.io/en/nix/#nix)