mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-22 15:03:28 +00:00
lib/types: Introduce lazyAttrsOf
The standard attrsOf is strict in its *values*, meaning it's impossible to access only one attribute value without evaluating all others as well. lazyAttrsOf is a version that doesn't have that problem, at the expense of conditional definitions not properly working anymore.
This commit is contained in:
parent
4268b4f9cf
commit
b48717d1eb
@ -302,6 +302,30 @@ rec {
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
};
|
||||
|
||||
# A version of attrsOf that's lazy in its values at the expense of
|
||||
# conditional definitions not working properly. E.g. defining a value with
|
||||
# `foo.attr = mkIf false 10`, then `foo ? attr == true`, whereas with
|
||||
# attrsOf it would correctly be `false`. Accessing `foo.attr` would throw an
|
||||
# error that it's not defined. Use only if conditional definitions don't make sense.
|
||||
lazyAttrsOf = elemType: mkOptionType rec {
|
||||
name = "lazyAttrsOf";
|
||||
description = "lazy attribute set of ${elemType.description}s";
|
||||
check = isAttrs;
|
||||
merge = loc: defs:
|
||||
zipAttrsWith (name: defs:
|
||||
let merged = mergeDefinitions (loc ++ [name]) elemType defs;
|
||||
# mergedValue will trigger an appropriate error when accessed
|
||||
in merged.optionalValue.value or elemType.emptyValue.value or merged.mergedValue
|
||||
)
|
||||
# Push down position info.
|
||||
(map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs);
|
||||
emptyValue = { value = {}; };
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: lazyAttrsOf (elemType.substSubModules m);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
};
|
||||
|
||||
# List or attribute set of ...
|
||||
loaOf = elemType:
|
||||
let
|
||||
|
@ -360,6 +360,31 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<varname>types.lazyAttrsOf</varname> <replaceable>t</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
An attribute set of where all the values are of
|
||||
<replaceable>t</replaceable> type. Multiple definitions result in the
|
||||
joined attribute set. This is the lazy version of <varname>types.attrsOf
|
||||
</varname>, allowing attributes to depend on each other.
|
||||
<warning><para>
|
||||
This version does not fully support conditional definitions! With an
|
||||
option <varname>foo</varname> of this type and a definition
|
||||
<literal>foo.attr = lib.mkIf false 10</literal>, evaluating
|
||||
<literal>foo ? attr</literal> will return <literal>true</literal>
|
||||
even though it should be false. Accessing the value will then throw
|
||||
an error. For types <replaceable>t</replaceable> that have an
|
||||
<literal>emptyValue</literal> defined, that value will be returned
|
||||
instead of throwing an error. So if the type of <literal>foo.attr</literal>
|
||||
was <literal>lazyAttrsOf (nullOr int)</literal>, <literal>null</literal>
|
||||
would be returned instead for the same <literal>mkIf false</literal> definition.
|
||||
</para></warning>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<varname>types.loaOf</varname> <replaceable>t</replaceable>
|
||||
|
Loading…
Reference in New Issue
Block a user