mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-22 23:13:19 +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; };
|
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 ...
|
# List or attribute set of ...
|
||||||
loaOf = elemType:
|
loaOf = elemType:
|
||||||
let
|
let
|
||||||
|
@ -360,6 +360,31 @@
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
<varname>types.loaOf</varname> <replaceable>t</replaceable>
|
<varname>types.loaOf</varname> <replaceable>t</replaceable>
|
||||||
|
Loading…
Reference in New Issue
Block a user