Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 360e57a567a7
Choose a base ref
...
head repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8252861507ef
Choose a head ref
  • 1 commit
  • 3 files changed
  • 2 contributors

Commits on Oct 21, 2019

  1. lib/trivial: add pipe function

    `pipe` is a useful operator for creating pipelines of functions.
    
    It works around the usual problem of e.g. string operations becoming
    deeply nested functions.
    
    In principle, there are four different ways this function could be
    written:
    
    pipe val [ f1 .. fn ]
    pipe val [ fn .. f1 ]
    compose [ f1 .. fn ] val
    compose [ fn .. f1 ] val
    
    The third and fourth form mirror composition of functions, they would
    be the same as e.g. `(f1 << f2 << f3 .. << fn) val`.
    However, it is not clear which direction the list should have (as one
    can see in the second form, which is the most absurd.
    
    In order not to confuse users, we decide for the most “intuitive”
    form, which mirrors the way unix pipes work (thus the name `pipe`).
    The flow of data goes from left to right.
    
    Co-Authored-By: Silvan Mosberger <infinisil@icloud.com>
    Profpatsch and infinisil committed Oct 21, 2019
    Copy the full SHA
    8252861 View commit details
Showing with 64 additions and 2 deletions.
  1. +2 −2 lib/default.nix
  2. +25 −0 lib/tests/misc.nix
  3. +37 −0 lib/trivial.nix
4 changes: 2 additions & 2 deletions lib/default.nix
Original file line number Diff line number Diff line change
@@ -57,8 +57,8 @@ let
hasAttr head isAttrs isBool isInt isList isString length
lessThan listToAttrs pathExists readFile replaceStrings seq
stringLength sub substring tail;
inherit (trivial) id const concat or and bitAnd bitOr bitXor bitNot
boolToString mergeAttrs flip mapNullable inNixShell min max
inherit (trivial) id const pipe concat or and bitAnd bitOr bitXor
bitNot boolToString mergeAttrs flip mapNullable inNixShell min max
importJSON warn info showWarnings nixpkgsVersion version mod compare
splitByAndCompare functionArgs setFunctionArgs isFunction;
inherit (fixedPoints) fix fix' converge extends composeExtensions
25 changes: 25 additions & 0 deletions lib/tests/misc.nix
Original file line number Diff line number Diff line change
@@ -18,6 +18,31 @@ runTests {
expected = 2;
};

testPipe = {
expr = pipe 2 [
(x: x + 2) # 2 + 2 = 4
(x: x * 2) # 4 * 2 = 8
];
expected = 8;
};

testPipeEmpty = {
expr = pipe 2 [];
expected = 2;
};

testPipeStrings = {
expr = pipe [ 3 4 ] [
(map toString)
(map (s: s + "\n"))
concatStrings
];
expected = ''
3
4
'';
};

/*
testOr = {
expr = or true false;
37 changes: 37 additions & 0 deletions lib/trivial.nix
Original file line number Diff line number Diff line change
@@ -29,6 +29,43 @@ rec {
# Value to ignore
y: x;

/* Pipes a value through a list of functions, left to right.
Type: pipe :: a -> [<functions>] -> <return type of last function>
Example:
pipe 2 [
(x: x + 2) # 2 + 2 = 4
(x: x * 2) # 4 * 2 = 8
]
=> 8
# ideal to do text transformations
pipe [ "a/b" "a/c" ] [
# create the cp command
(map (file: ''cp "${src}/${file}" $out\n''))
# concatenate all commands into one string
lib.concatStrings
# make that string into a nix derivation
(pkgs.runCommand "copy-to-out" {})
]
=> <drv which copies all files to $out>
The output type of each function has to be the input type
of the next function, and the last function returns the
final value.
*/
pipe = val: functions:
let reverseApply = x: f: f x;
in builtins.foldl' reverseApply val functions;
/* note please don’t add a function like `compose = flip pipe`.
This would confuse users, because the order of the functions
in the list is not clear. With pipe, it’s obvious that it
goes first-to-last. With `compose`, not so much.
*/

## Named versions corresponding to some builtin operators.