libexpr/builtins: Document scopedImport
This also allows removing a static initialization of a primop. Co-authored-by: Eelco Dolstra <edolstra@gmail.com> Change-Id: I74da68205630f658b239e4327bf5e27bfc1b91da
This commit is contained in:
co-authored by
Eelco Dolstra
parent
2a308bca00
commit
f01555105a
@@ -0,0 +1,80 @@
|
||||
---
|
||||
name: scopedImport
|
||||
implementation: "[](EvalState & state, Value ** args, Value & v) { import(state, *args[1], args[0], v); }"
|
||||
args: [scope, path]
|
||||
renameInGlobalScope: false
|
||||
---
|
||||
|
||||
Functions like [`import`](#builtins-import) with the exceptions that
|
||||
it takes a `scope`, which is a set of attributes to be added to the
|
||||
lexical scope of the expression.
|
||||
|
||||
This essentially allows overriding the ambient builtin variables.
|
||||
|
||||
For example, if `foo.nix` is a file containing the following content:
|
||||
|
||||
```nix
|
||||
x
|
||||
```
|
||||
|
||||
then the following expression
|
||||
|
||||
```nix
|
||||
scopedImport { x = 1; } ./foo.nix
|
||||
```
|
||||
|
||||
will evaluate to `1`.
|
||||
|
||||
This allows removing function arguments specifications in nix expressions,
|
||||
for example, a package definition `bar.nix`:
|
||||
|
||||
```nix
|
||||
{ stdenv, fetchurl, libfoo }:
|
||||
|
||||
stdenv.mkDerivation { ... buildInputs = [ libfoo ]; }
|
||||
```
|
||||
|
||||
can be rewritten as:
|
||||
|
||||
```nix
|
||||
stdenv.mkDerivation { ... buildInputs = [ libfoo ]; }
|
||||
```
|
||||
|
||||
and imported via:
|
||||
|
||||
```nix
|
||||
bar = scopedImport pkgs ./bar.nix;
|
||||
```
|
||||
|
||||
which remove some duplication of code.
|
||||
|
||||
Another application is overriding builtin functions or constants, e.g. to
|
||||
trace all calls to `map`, one can do:
|
||||
|
||||
```nix
|
||||
let
|
||||
overrides = {
|
||||
map = f: xs: builtins.trace "map called!" (map f xs);
|
||||
|
||||
# Ensure that our override gets propagated by calls to
|
||||
# import/scopedImport.
|
||||
import = fn: scopedImport overrides fn;
|
||||
|
||||
scopedImport = attrs: fn: scopedImport (overrides // attrs) fn;
|
||||
|
||||
# Also update ‘builtins’.
|
||||
builtins = builtins // overrides;
|
||||
};
|
||||
in scopedImport overrides ./bla.nix
|
||||
```
|
||||
|
||||
Similarly, one can simply extend the set of builtin functions.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> A downside of using `scopedImport` is that it bypasses the evaluation cache.
|
||||
> This means that importing a file multiple times will lead to multiple parsings
|
||||
> and evaluations.
|
||||
>
|
||||
> Please note also that the files imported via `scopedImport` contain free variables
|
||||
> and thus cannot be imported using the regular `import`.
|
||||
@@ -125,6 +125,7 @@ builtin_definitions = files(
|
||||
'builtins/readFileType.md',
|
||||
'builtins/removeAttrs.md',
|
||||
'builtins/replaceStrings.md',
|
||||
'builtins/scopedImport.md',
|
||||
'builtins/seq.md',
|
||||
'builtins/sort.md',
|
||||
'builtins/split.md',
|
||||
|
||||
@@ -251,13 +251,6 @@ static void import(EvalState & state, Value & vPath, Value * vScope, Value & v)
|
||||
}
|
||||
}
|
||||
|
||||
static RegisterPrimOp primop_scopedImport(PrimOp{
|
||||
{.name = "scopedImport",
|
||||
.arity = 2,
|
||||
.fun = [](EvalState & state, Value ** args, Value & v) { import(state, *args[1], args[0], v); }
|
||||
}
|
||||
});
|
||||
|
||||
static void prim_import(EvalState & state, Value * * args, Value & v)
|
||||
{
|
||||
import(state, *args[0], nullptr, v);
|
||||
|
||||
Reference in New Issue
Block a user