mkdir nib/std && replace --all 'with' 'let ... in'

This commit is contained in:
Emile Clark-Boman 2025-12-14 20:47:34 +10:00
parent f9bb6ad937
commit fd008cd2e1
11 changed files with 108 additions and 104 deletions

View file

@ -1,125 +0,0 @@
{nib, ...}:
with builtins;
with nib.types; rec {
nameValuePair = name: value: {inherit name value;};
identityAttrs = value: {${value} = value;};
identityAttrsList = values: map (v: identityAttrs v) values;
/**
Generate an attribute set by mapping a function over a list of
attribute names.
# Inputs
`names`
: Names of values in the resulting attribute set.
`f`
: A function, given the name of the attribute, returns the attribute's value.
# Type
```
genAttrs :: [ String ] -> (String -> Any) -> AttrSet
```
# Examples
:::{.example}
## `lib.attrsets.genAttrs` usage example
```nix
genAttrs [ "foo" "bar" ] (name: "x_" + name)
=> { foo = "x_foo"; bar = "x_bar"; }
```
:::
*/
genAttrs = names: f: genAttrs' names (n: nameValuePair n (f n));
/**
Like `genAttrs`, but allows the name of each attribute to be specified in addition to the value.
The applied function should return both the new name and value as a `nameValuePair`.
::: {.warning}
In case of attribute name collision the first entry determines the value,
all subsequent conflicting entries for the same name are silently ignored.
:::
# Inputs
`xs`
: A list of strings `s` used as generator.
`f`
: A function, given a string `s` from the list `xs`, returns a new `nameValuePair`.
# Type
```
genAttrs' :: [ Any ] -> (Any -> { name :: String; value :: Any; }) -> AttrSet
```
# Examples
:::{.example}
## `lib.attrsets.genAttrs'` usage example
```nix
genAttrs' [ "foo" "bar" ] (s: nameValuePair ("x_" + s) ("y_" + s))
=> { x_foo = "y_foo"; x_bar = "y_bar"; }
```
:::
*/
genAttrs' = xs: f: listToAttrs (map f xs);
mapAttrsRecursiveCond = cond: f: set: let
recurse = path:
mapAttrs (
name: value: let
next = path ++ [name];
in
if isAttrs value && cond value
then recurse next value
else f next value
);
in
recurse [] set;
mapAttrsRecursive = f: set: mapAttrsRecursiveCond (as: true) f set;
# form: attrValueAt :: xs -> path -> value
# given path as a list of strings, return that value of an
# attribute set at that path
attrValueAt = let
value = foldl (l: r:
if isAttrs l && hasAttr r l
then l.${r}
else null);
in
nullableToMaybe value;
mergeAttrsList = list: let
# `binaryMerge start end` merges the elements at indices `index` of `list` such that `start <= index < end`
# Type: Int -> Int -> Attrs
binaryMerge = start: end:
# assert start < end; # Invariant
if end - start >= 2
then
# If there's at least 2 elements, split the range in two, recurse on each part and merge the result
# The invariant is satisfied because each half will have at least 1 element
binaryMerge start (start + (end - start) / 2) // binaryMerge (start + (end - start) / 2) end
else
# Otherwise there will be exactly 1 element due to the invariant, in which case we just return it directly
elemAt list start;
in
if list == []
then
# Calling binaryMerge as below would not satisfy its invariant
{}
else binaryMerge 0 (length list);
}

View file

@ -1,18 +1,11 @@
{nib, ...} @ args: let
attrs = import ./attrs.nix args;
fault = import ./fault.nix args;
lists = import ./lists.nix args;
maybe = import ./maybe.nix args;
res = import ./res.nix args;
in
attrs.mergeAttrsList [
nib.std.mergeAttrsList [
# submodule is included directly to this module (ie self.myFunc)
attrs
fault
lists
maybe
res
# submodule content is accessible first by submodule name
# then by the name of the content (ie self.submodule.myFunc)
]

View file

@ -1,5 +1,4 @@
{...}:
with builtins; rec {
{...}: rec {
# Fault Monad
# Wrapper around an error (ie builtins.abort)
Fault = error: {
@ -7,7 +6,7 @@ with builtins; rec {
};
# Pattern Matching
isFault = F: attrNames F == ["_error_"];
isFault = F: builtins.attrNames F == ["_error_"];
# Unwrap (Monadic Return Operation)
unwrapFault = F: F._error_;

View file

@ -1,55 +0,0 @@
{...}:
with builtins; rec {
foldl = op: nul: list: let
foldl' = n:
if n == -1
then nul
else op (foldl' (n - 1)) (elemAt list n);
in
foldl' (length list - 1);
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];
findFirstIndex = pred: default: list: let
# A naive recursive implementation would be much simpler, but
# would also overflow the evaluator stack. We use `foldl'` as a workaround
# because it reuses the same stack space, evaluating the function for one
# element after another. We can't return early, so this means that we
# sacrifice early cutoff, but that appears to be an acceptable cost. A
# clever scheme with "exponential search" is possible, but appears over-
# engineered for now. See https://github.com/NixOS/nixpkgs/pull/235267
# Invariant:
# - if index < 0 then el == elemAt list (- index - 1) and all elements before el didn't satisfy pred
# - if index >= 0 then pred (elemAt list index) and all elements before (elemAt list index) didn't satisfy pred
#
# We start with index -1 and the 0'th element of the list, which satisfies the invariant
resultIndex =
foldl' (
index: el:
if index < 0
then
# No match yet before the current index, we need to check the element
if pred el
then
# We have a match! Turn it into the actual index to prevent future iterations from modifying it
-index - 1
else
# Still no match, update the index to the next element (we're counting down, so minus one)
index - 1
else
# There's already a match, propagate the index without evaluating anything
index
) (-1)
list;
in
if resultIndex < 0
then default
else resultIndex;
findFirst = pred: default: list: let
index = findFirstIndex pred null list;
in
if index == null
then default
else elemAt list index;
}

View file

@ -1,6 +1,6 @@
{nib, ...}:
with builtins;
with nib.types; let
{nib, ...}: let
Res = nib.types.Res;
findFirst = nib.std.findFirst;
# TODO: try get enum generation working (and other type constructors)
# Maybe = mkEnum "nib::Maybe" {
# Some = mkEnumVariant {value = "nix::String";};
@ -66,7 +66,7 @@ in rec {
None = Maybe false null;
# Pattern Matching
isMaybe = T: attrNames T == ["_some_" "_value_"];
isMaybe = T: builtins.attrNames T == ["_some_" "_value_"];
isSome = T: isMaybe T && T._some_;
isNone = T: isMaybe T && !T._some_;

View file

@ -1,6 +1,6 @@
{nib, ...}:
with builtins;
with nib.types; rec {
{nib, ...}: let
findFirst = nib.std.findFirst;
in rec {
# Res (Result) Monad
Res = success: value: {
_success_ = success;
@ -12,7 +12,7 @@ with nib.types; rec {
Err' = Err "err";
# Pattern Matching
isRes = R: attrNames R == ["_success_" "_value_"];
isRes = R: builtins.attrNames R == ["_success_" "_value_"];
isOk = R: isRes R && R._success_;
isErr = R: isRes R && !R._success_;