From 5b953ce62e2fb9f414512593c94c4951eb08b5f5 Mon Sep 17 00:00:00 2001 From: sharpchen Date: Tue, 17 Dec 2024 19:55:27 +0800 Subject: [PATCH] main --- .../Language Features/Assertion.md | 3 - .../Conditional Expression and Flow.md | 22 ---- .../Declaration and Expression.md | 11 -- .../Language Features/Logical Implication.md | 1 - .../Language Features/With-Expression.md | 53 -------- .../Primitive Types/Function and Lambda.md | 75 ----------- .../Primitive Types/Path Literal.md | 25 ---- .../Primitive Types/String.md | 65 --------- .../Nix/docs/1.Language/Control Flow.md | 74 +++++++++++ docs/document/Nix/docs/1.Language/Function.md | 96 ++++++++++++++ .../Object and Collection.md} | 124 +++++++++++------- docs/document/Nix/docs/1.Language/Path.md | 49 +++++++ docs/document/Nix/docs/1.Language/String.md | 99 ++++++++++++++ .../1. Getting Started.md | 0 .../2. Adding Channels.md | 0 .../3. Flake Structure.md | 0 .../Nix/docs/{Nix Flakes => Flakes}/t.md | 0 17 files changed, 398 insertions(+), 299 deletions(-) delete mode 100644 docs/document/Nix/docs/1. The Nix Language/Language Features/Assertion.md delete mode 100644 docs/document/Nix/docs/1. The Nix Language/Language Features/Conditional Expression and Flow.md delete mode 100644 docs/document/Nix/docs/1. The Nix Language/Language Features/Declaration and Expression.md delete mode 100644 docs/document/Nix/docs/1. The Nix Language/Language Features/Logical Implication.md delete mode 100644 docs/document/Nix/docs/1. The Nix Language/Language Features/With-Expression.md delete mode 100644 docs/document/Nix/docs/1. The Nix Language/Primitive Types/Function and Lambda.md delete mode 100644 docs/document/Nix/docs/1. The Nix Language/Primitive Types/Path Literal.md delete mode 100644 docs/document/Nix/docs/1. The Nix Language/Primitive Types/String.md create mode 100644 docs/document/Nix/docs/1.Language/Control Flow.md create mode 100644 docs/document/Nix/docs/1.Language/Function.md rename docs/document/Nix/docs/{1. The Nix Language/Primitive Types/Set and List.md => 1.Language/Object and Collection.md} (51%) create mode 100644 docs/document/Nix/docs/1.Language/Path.md create mode 100644 docs/document/Nix/docs/1.Language/String.md rename docs/document/Nix/docs/{Nix Flakes => Flakes}/1. Getting Started.md (100%) rename docs/document/Nix/docs/{Nix Flakes => Flakes}/2. Adding Channels.md (100%) rename docs/document/Nix/docs/{Nix Flakes => Flakes}/3. Flake Structure.md (100%) rename docs/document/Nix/docs/{Nix Flakes => Flakes}/t.md (100%) diff --git a/docs/document/Nix/docs/1. The Nix Language/Language Features/Assertion.md b/docs/document/Nix/docs/1. The Nix Language/Language Features/Assertion.md deleted file mode 100644 index e6cc172e..00000000 --- a/docs/document/Nix/docs/1. The Nix Language/Language Features/Assertion.md +++ /dev/null @@ -1,3 +0,0 @@ -# Assertion - -## diff --git a/docs/document/Nix/docs/1. The Nix Language/Language Features/Conditional Expression and Flow.md b/docs/document/Nix/docs/1. The Nix Language/Language Features/Conditional Expression and Flow.md deleted file mode 100644 index e87909cc..00000000 --- a/docs/document/Nix/docs/1. The Nix Language/Language Features/Conditional Expression and Flow.md +++ /dev/null @@ -1,22 +0,0 @@ -# Conditional Expression adn Flow - -## Conditional flow - - -```nix - -``` - -## Ternary operation - -```nix -if cond then true_case else false_case -``` - -## Null-Coalescing operator - -Use `or` to perform value fallback if target value is null. - -```nix -let name = { name = "jane"; age = 18 }.name or "john smith"; in {} -``` diff --git a/docs/document/Nix/docs/1. The Nix Language/Language Features/Declaration and Expression.md b/docs/document/Nix/docs/1. The Nix Language/Language Features/Declaration and Expression.md deleted file mode 100644 index 018f74bf..00000000 --- a/docs/document/Nix/docs/1. The Nix Language/Language Features/Declaration and Expression.md +++ /dev/null @@ -1,11 +0,0 @@ -# Declaration and Expression - -## Declaring variables - -`nix` has functional flavor that declares like math expressions, which declares variables before expressions. - -So `let [ = ]; in ` - -```nix -let a = 1; b = 2; in a + b -``` diff --git a/docs/document/Nix/docs/1. The Nix Language/Language Features/Logical Implication.md b/docs/document/Nix/docs/1. The Nix Language/Language Features/Logical Implication.md deleted file mode 100644 index 0a3aab91..00000000 --- a/docs/document/Nix/docs/1. The Nix Language/Language Features/Logical Implication.md +++ /dev/null @@ -1 +0,0 @@ -# Logical Implication diff --git a/docs/document/Nix/docs/1. The Nix Language/Language Features/With-Expression.md b/docs/document/Nix/docs/1. The Nix Language/Language Features/With-Expression.md deleted file mode 100644 index 86a293c4..00000000 --- a/docs/document/Nix/docs/1. The Nix Language/Language Features/With-Expression.md +++ /dev/null @@ -1,53 +0,0 @@ -# With-Expression - -## Deconstruct from set into scope - -`with` keyword can be used to introduce variables from a attribute set into current scope: - -```nix - -let foo = { bar = "???"; baz = "!!!" }; in - ${foo.bar} + ${foo.baz} # `bar` and `baz` are introduced -``` - -equivalent to - -```nix -let foo = { bar = "???"; baz = "!!!" }; in - with foo; - ${bar} + ${baz} # `bar` and `baz` are introduced -``` - -```nix -f = { x ? 1, y ? 2, ... }@args: with args; x + y + z -``` - -```nix -foo = rec { - p = { x = 1; y = 1; }; - bar = with p; [ x y ]; -}; -``` - -## Importing from another module - -When another module is imported, all attributes will be deconstructed from the set into scope. - -```nix -let foo = null; in - with (import ./foo.nix); -``` - -## Practical usage - -```nix -{ config, pkgs, ... }: - -{ - home.packages = with pkgs; [ - git - ripgrep - neovim - ]; -} -``` diff --git a/docs/document/Nix/docs/1. The Nix Language/Primitive Types/Function and Lambda.md b/docs/document/Nix/docs/1. The Nix Language/Primitive Types/Function and Lambda.md deleted file mode 100644 index b6ecc251..00000000 --- a/docs/document/Nix/docs/1. The Nix Language/Primitive Types/Function and Lambda.md +++ /dev/null @@ -1,75 +0,0 @@ -# Function and Lambda - -## Lambda - -Fucntion form in `nix` is like `:(|)` - -```nix -n: n % 2 != 0 # tells whether a number is odd -``` - -## Function call - -Function call by parameters after function or function variable - -```nix -let is_odd = n: n % 2 != 0; in { - is_odd 3 # false -} -``` - -## Curried function - -Multiple parameters for `nix` function? Sadly no such thing exists in `nix`. -But one workround is currying. Currying simply stores state into next function returned from previous, to perform the chaining. -It's recursive-like, but with absolute recursion count(which is the paramter count needed). - -```nix -let add = x: y: x + y; in add 2 3 # returns 5 -``` - -## Set pattern paramters(Named parameters) - -Another workround for multiple paramters for function is using *set parttern*. -Paramters are separated by comma instead of semicolon. - -```nix -let format_person = { name, age }: { name = name; age = age }; -in - format_person { name = "jane"; age = 18 } -``` - -:::info -Set parttern is similar to named paramters, they're all named, can be sepecified by any order. -::: - -## Variadic parameter - -`args` binds to the whole set excluding the optional attribute. - -```nix -let format_person = { name, age, height ? 0, ... } @args: "${toJSON args}"; -in - format_person { name = "john smith"; age = 18 } # `height` is not included in json -``` - -:::info -If no other paramters are expected, do omit `...` to prevent messing things up. -::: - -There's no signiture checking for argument count, so adding attributes that are not defined in function definition is ok. - -```nix -let format_person = { name, age, height ? 0, ... } @args: "${toJSON args}"; -in - format_person { name = "john smith"; weight = 60 } # weight does not appear in parameter list but it's valid -``` - -## Optional paramter - - -```nix -let format_person = { name ? "john smith", age ? null }: "${name} aged ${age}"; -in - format_person { name = "jane" } -``` diff --git a/docs/document/Nix/docs/1. The Nix Language/Primitive Types/Path Literal.md b/docs/document/Nix/docs/1. The Nix Language/Primitive Types/Path Literal.md deleted file mode 100644 index d4bb4338..00000000 --- a/docs/document/Nix/docs/1. The Nix Language/Primitive Types/Path Literal.md +++ /dev/null @@ -1,25 +0,0 @@ -# Path Literal - -Paths are natively presented in `nix` instead of as strings - -## Path interpolation - -Path can be created from string evaluation - -```nix -rec { - user = "john"; - home = /home/${user}/ -} -``` - -:::info -Path interpolation requires at least one slash before any value were interpolated. -`${user}/${email}` wound be lowered as a division operation while `./${user}/${email}` is a path -::: - -## Path concatenation - -```nix -./foo/bar + "file.txt" -``` diff --git a/docs/document/Nix/docs/1. The Nix Language/Primitive Types/String.md b/docs/document/Nix/docs/1. The Nix Language/Primitive Types/String.md deleted file mode 100644 index 1c0ef681..00000000 --- a/docs/document/Nix/docs/1. The Nix Language/Primitive Types/String.md +++ /dev/null @@ -1,65 +0,0 @@ -# String - -## Single-line string - -```nix -"single" -``` - -## Multi-line string - -When single-line string exceeds column number you want, use multi-line string. -Leading two spaces are trimmed - -```nix -'' - this is a - linebreak! -'' -``` - -is equivalent to - -```nix -"this is a \nlinebreak!" -``` - -Multi-line string is typically useful to write shell scripts inside `nix`. - -```nix -stdenv.mkDerivation { - postInstall = - '' - mkdir $out/bin $out/etc - cp foo $out/bin - echo "Hello World" > $out/etc/foo.conf - ${if enableBar then "cp bar $out/bin" else ""} - ''; -} -``` - -### Escaping - -To escape in multi-line, prefix with `''` - -```nix -'' - This is a dollar sign: - ''$ - This is a new line ''\n - This is a single quote: ''\' - This is also a single quote: ''' -'' -``` - -## String concatenation - -```nix -"foo" + "bar" -``` - -## String interpolation - -```nix -"git path managed by nix: ${pkgs.git}" -``` diff --git a/docs/document/Nix/docs/1.Language/Control Flow.md b/docs/document/Nix/docs/1.Language/Control Flow.md new file mode 100644 index 00000000..dbf5a98c --- /dev/null +++ b/docs/document/Nix/docs/1.Language/Control Flow.md @@ -0,0 +1,74 @@ +# Control Flow + +Nix is a functional language to behave as no side-effect, all variables are isolated in scope and all controls flow statement can have implicit return. + +## Let-in + +`let..in` statement is used to create a isolated scope to perform operation on variable declared after `let` and requires a return after `in`. + +```nix +let + foo = 1; +in + foo # foo is returned +``` + +Since it supports implicit return, you store the value to a variable. + +```nix +let + foo = # [!code highlight] + let # [!code highlight] + bar = 123; # [!code highlight] + in # [!code highlight] + bar + 1; # [!code highlight] +in +foo +``` + +> [!NOTE] +> Child scope inside `let..in` statement can access variables from parent scope. + +## Value Fallback + +```nix +foo or "foo" +# equvalent to +if foo != null then foo else "foo" +``` + +## With Local Expanding + +`with` works similarly to `let..in`, it creates a new scope and implicitly declares all attributes of a set as variables into the new scope. +```nix +let + foo = { + bar = 123; + baz = 123; + }; +in +with foo; +{ + inherit bar; # foo.bar and foo.baz is available in scope as variables # [!code highlight] + inherit baz; # [!code highlight] +} +``` + +If a attribute expanded by `with` conflicts with any variable in scope by its name, **the variable is preferred**. + +```nix +let + foo = { + bar = 123; + }; + bar = 456; # [!code highlight] +in +with foo; +{ + inherit bar; # bar = 456 # [!code highlight] +} +``` + +## Assertion + + diff --git a/docs/document/Nix/docs/1.Language/Function.md b/docs/document/Nix/docs/1.Language/Function.md new file mode 100644 index 00000000..1b993172 --- /dev/null +++ b/docs/document/Nix/docs/1.Language/Function.md @@ -0,0 +1,96 @@ +# Function + +```nix +n: n % 2 != 0 # tells whether a number is odd +``` + +## Function call + +Function call by parameters after function or function variable + +```nix +let is_odd = n: n % 2 != 0; in { + is_odd 3 # false +} +``` + +## Curried Function + +Multiple parameters for `nix` function? Sadly no such thing exists in `nix`. +But one workaround is currying. Currying simply stores state into next function returned from previous, to perform the chaining. +It's recursive-like, but with absolute recursion count(which is the parameter count needed). + +```nix +let add = x: y: x + y; in add 2 3 # returns 5 +``` + +## Named Parameters + +Another workaround for multiple paramters for function is using *set parttern*. + +```nix +let format_person = { name, age }: { name = name; age = age }; +in + format_person { name = "jane"; age = 18 } +``` + +## Optional Parameter + +```nix +let + format_person = + { + name ? "john smith", + age ? null, + }: + "${name} aged ${age}"; +in +format_person { name = "jane"; } +``` + +> [!NOTE] +> Set parttern is similar to named paramters, they're all named, can be sepecified by any order. + +## Parameter List + +`args` binds to the whole set excluding the optional attribute. + +```nix +let + format_person = + { + name, + age, + height ? 0, + ... + }@args: + "${builtins.toJSON args}"; +in +format_person { + name = "john smith"; + age = 18; +} # `height` is not included in json +``` + +> [!NOTE] +> If no other paramters are expected, do omit `...` to prevent messing things up. + +There's no signiture checking for argument count, so adding attributes that are not defined in function definition is ok. + +```nix +let + format_person = + { + name, + age, + height ? 0, + ... + }@args: + "${builtins.toJSON args}"; +in +format_person { + name = "john smith"; + weight = 60; # [!code highlight] +} # weight does not appear in parameter list but it's valid +``` + diff --git a/docs/document/Nix/docs/1. The Nix Language/Primitive Types/Set and List.md b/docs/document/Nix/docs/1.Language/Object and Collection.md similarity index 51% rename from docs/document/Nix/docs/1. The Nix Language/Primitive Types/Set and List.md rename to docs/document/Nix/docs/1.Language/Object and Collection.md index 3b04fc3e..5c86058e 100644 --- a/docs/document/Nix/docs/1. The Nix Language/Primitive Types/Set and List.md +++ b/docs/document/Nix/docs/1.Language/Object and Collection.md @@ -1,6 +1,10 @@ -# Set and List +# Object and Collection -## Set +Nix has only two kinds of collection: +- Attribute Set: a similar concept to object literal. +- List: generic bucket for elements. + +## Attribute Set Set is similar to object literal in some languages like javascript and lua. Properties of a set are called attributes in `nix` @@ -18,10 +22,13 @@ baz = { } in { } ``` -### Recursive set +### Recursive Set Attributes can reuse value from other attributes in scope, the set should annotate with leading `rec` +> [!TIP] +> The attribute order doesn't matter. + ```nix rec { area = height * width; @@ -30,41 +37,49 @@ rec { } ``` -### Attribute inheriting - +### Expanding Attributes ```nix -let foo = "???"; baz = "!!!"; in { - inherit foo baz; - bar = "bar"; +let + foo = 123; +in +{ + inherit foo; } -# equivalent to +# equvalent to -let foo = "???"; baz = "!!!" in { +let + foo = 123; +in +{ foo = foo; - baz = baz; - bar = "bar"; } ``` -Inherit from another set: +Can expand multiple attributes from another attribute set: ```nix -let foo = { bar = "!!!"; baz = "???" }; in { +let + foo = { bar = 123; baz = "123"; }; +in +{ inherit (foo) bar baz; } -``` -equivalent to -```nix -let foo = { bar = "!!!"; baz = "???" }; in { +# equvalent to + +let + foo = { bar = 123; baz = "123"; }; +in +{ bar = foo.bar; baz = foo.baz; } + ``` -### Accessing attributes +### Access Attribute Use `.` to access attribute of a set with either identifier or key string. @@ -80,47 +95,51 @@ let languages = { } ``` -### Telling whether a set has a attribute +### Searching Path Validation -Use `?` operator to tell whether a key or attribute path is registered in a set +Use `?` to validate whether the search path exists in an attribute set. ```nix -let foo = { bar = null; baz = { qux = 123 }; }; in - if foo ? bar then trace "bar exists in foo"; # bar is the key name - if foo ? baz.qux then trace "baz.qux exists in foo"; # baz.qux is the attribute path - if foo.baz ? qux then trace "qux exists in foo.baz" +let + foo = { + bar = null; + baz = { + qux = 123; + }; + }; +in +[ + (foo ? bar) + (foo.baz ? qux) + (foo ? baz.qux) # [!code highlight] +] ``` -## Updating a set +### Merging -`//` operator will try to merge left and right operand, if attribute with same name has different values, the value from right operand is taken. +`//` operator will try to merge left and right operand, if attribute with same name has different values, the value from right operand will be taken. ```nix { foo = null; bar = null } // { foo = 1; baz = null } # retuns { foo = 1; bar = null; baz = null; } ``` -## List +### Callable Set -List elements are separated by spaces +Specifying `__functor` meta attribute to make the attribute set to be a callable function as well. +The functor can have a parameter `self` that targets to the attribute set itself. +The nested function takes the actual paramter can be applied to the functor. ```nix -["a" 1 { foo = "bar" } (func 1)] -``` - -:::info -To evaluate value returned from a function as a element of list, enclose it by `()`. -::: - -### List concatenation - -Use `++` operator - -```nix -["a", 1 { foo = "bar" }] ++ [1 2 3] +let +foo = { + __functor = self: x: builtins.toString x; +}; +in + foo 123 # x is 123 here ``` -## Comparsion +## Equality Checking List and set are compared by their structure, not their references. @@ -129,6 +148,23 @@ let foo = { bar = { baz = {} }; }; qux = { bar = { baz = {} }; }; in - assert foo == qux; true # true + assert foo == qux; # true +``` + +## List + +List elements are separated by spaces +```nix +["a" 1 { foo = "bar" } (func 1)] ``` + +> [!NOTE] +> To evaluate value returned from a function as a element of list, enclose it by `()`. + +### Concatenation + +```nix +["a", 1 { foo = "bar" }] ++ [1 2 3] +``` + diff --git a/docs/document/Nix/docs/1.Language/Path.md b/docs/document/Nix/docs/1.Language/Path.md new file mode 100644 index 00000000..4d76a2c7 --- /dev/null +++ b/docs/document/Nix/docs/1.Language/Path.md @@ -0,0 +1,49 @@ +# Path Literal + +Paths are natively presented in `nix` instead of as strings + +## Interpolation + +Path can be created from string evaluation + +```nix +rec { + user = "john"; + home = /home/${user}/ +} +``` + +> [!NOTE] +> Path interpolation requires at least one slash before any value were interpolated. +>`${user}/${email}` wound be lowered as a division operation while `./${user}/${email}` is a path + +## From `NIX_PATH` + +Paths from `NIX_PATH` variable can be recognized directly using `<>`. +This is particularly useful when importing a registered nix channel. + +```nix +let + pkgs = import { }; +in + {} +``` + +## Concatenation + +```nix +./foo/bar + "file.txt" +``` + +## Evaluation + +Each evaluation for a path will inform nix to copy the file or directory into nix store. + +```console +nix-repl> "${~/projects}" +copying '/home/sharpchen/projects' to the store +``` + +> [!NOTE] +> You cannot interpolate paths created from `<>`. + diff --git a/docs/document/Nix/docs/1.Language/String.md b/docs/document/Nix/docs/1.Language/String.md new file mode 100644 index 00000000..172b87a0 --- /dev/null +++ b/docs/document/Nix/docs/1.Language/String.md @@ -0,0 +1,99 @@ +# String + +## Single-line string + +```nix +"single" +``` + +## Interpolation + +Nix does not handle string evaluation for all types but string, path and a nix package. +For other types, requires `builtins.toString`. + +```nix +"${123}" # cannot evaluate number to string # [!code error] +"${builtins.toString 123}" # ok # [!code highlight] +``` + +### Evaluation for Package + +A package object will be evaluated to the corresponding path in nix store. + +```nix +let + pkgs = import { }; +in + "${pkgs.bash}" # /nix/store/p6k7xp1lsfmbdd731mlglrdj2d66mr82-bash-5.2p37 +``` + +### Evaluation for Path + +Each evaluation for a path will inform nix to copy the file or directory into nix store. +The final value evaluated will be the path of the copy in nix store. + +```console +nix-repl> "${~/projects}" +copying '/home/sharpchen/projects' to the store +``` + +## Raw String + +```nix +'' + + I am a xml + +'' +``` + +### Syntax Injection + +Multi-line string is typically useful to write shell scripts inside `nix`. + +```nix +stdenv.mkDerivation { + postInstall = + '' + mkdir $out/bin $out/etc + cp foo $out/bin + echo "Hello World" > $out/etc/foo.conf + ${if enableBar then "cp bar $out/bin" else ""} + ''; +} +``` + +Some editors might support syntax injection for multi-line string. +Add filetype as comment before the string to inform syntax parser. + +```nix +let +foo = # js + '' + console.log('hello nix!') + ''; +bar = /* js */ '' + console.log('hello nix!') + ''; +in {} +``` + +### Escaping + +To escape in multi-line, prefix with `''` + +```nix +'' + This is a new line ''\n # [!code highlight] + This is a single quote: ''\' + This is also a single quote: ''' + This is not a interpolation ''${foo} # [!code highlight] +'' +``` + +## String Concatenation + +```nix +"foo" + "bar" +``` + diff --git a/docs/document/Nix/docs/Nix Flakes/1. Getting Started.md b/docs/document/Nix/docs/Flakes/1. Getting Started.md similarity index 100% rename from docs/document/Nix/docs/Nix Flakes/1. Getting Started.md rename to docs/document/Nix/docs/Flakes/1. Getting Started.md diff --git a/docs/document/Nix/docs/Nix Flakes/2. Adding Channels.md b/docs/document/Nix/docs/Flakes/2. Adding Channels.md similarity index 100% rename from docs/document/Nix/docs/Nix Flakes/2. Adding Channels.md rename to docs/document/Nix/docs/Flakes/2. Adding Channels.md diff --git a/docs/document/Nix/docs/Nix Flakes/3. Flake Structure.md b/docs/document/Nix/docs/Flakes/3. Flake Structure.md similarity index 100% rename from docs/document/Nix/docs/Nix Flakes/3. Flake Structure.md rename to docs/document/Nix/docs/Flakes/3. Flake Structure.md diff --git a/docs/document/Nix/docs/Nix Flakes/t.md b/docs/document/Nix/docs/Flakes/t.md similarity index 100% rename from docs/document/Nix/docs/Nix Flakes/t.md rename to docs/document/Nix/docs/Flakes/t.md