Replace hasAttr/getAttr calls with the ? and . operators
For NixOS evaluation, this gives a ~21% reduction in the number of values allocated and a ~4% speedup. It's also more readable.
This commit is contained in:
parent
0e120dc68f
commit
97220c973f
|
@ -20,8 +20,8 @@ rec {
|
||||||
let attr = head attrPath;
|
let attr = head attrPath;
|
||||||
in
|
in
|
||||||
if attrPath == [] then e
|
if attrPath == [] then e
|
||||||
else if hasAttr attr e
|
else if e ? ${attr}
|
||||||
then attrByPath (tail attrPath) default (getAttr attr e)
|
then attrByPath (tail attrPath) default e.${attr}
|
||||||
else default;
|
else default;
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,8 +44,7 @@ rec {
|
||||||
attrVals ["a" "b" "c"] as
|
attrVals ["a" "b" "c"] as
|
||||||
=> [as.a as.b as.c]
|
=> [as.a as.b as.c]
|
||||||
*/
|
*/
|
||||||
attrVals = nameList: set:
|
attrVals = nameList: set: map (x: set.${x}) nameList;
|
||||||
map (x: getAttr x set) nameList;
|
|
||||||
|
|
||||||
|
|
||||||
/* Return the values of all attributes in the given set, sorted by
|
/* Return the values of all attributes in the given set, sorted by
|
||||||
|
@ -66,7 +65,7 @@ rec {
|
||||||
=> [1 2]
|
=> [1 2]
|
||||||
*/
|
*/
|
||||||
catAttrs = builtins.catAttrs or
|
catAttrs = builtins.catAttrs or
|
||||||
(attr: l: concatLists (map (s: if hasAttr attr s then [(getAttr attr s)] else []) l));
|
(attr: l: concatLists (map (s: if s ? ${attr} then [s.${attr}] else []) l));
|
||||||
|
|
||||||
|
|
||||||
/* Filter an attribute set by removing all attributes for which the
|
/* Filter an attribute set by removing all attributes for which the
|
||||||
|
@ -77,7 +76,7 @@ rec {
|
||||||
=> { foo = 1; }
|
=> { foo = 1; }
|
||||||
*/
|
*/
|
||||||
filterAttrs = pred: set:
|
filterAttrs = pred: set:
|
||||||
listToAttrs (fold (n: ys: let v = getAttr n set; in if pred n v then [(nameValuePair n v)] ++ ys else ys) [] (attrNames set));
|
listToAttrs (fold (n: ys: let v = set.${n}; in if pred n v then [(nameValuePair n v)] ++ ys else ys) [] (attrNames set));
|
||||||
|
|
||||||
|
|
||||||
/* foldAttrs: apply fold functions to values grouped by key. Eg accumulate values as list:
|
/* foldAttrs: apply fold functions to values grouped by key. Eg accumulate values as list:
|
||||||
|
@ -87,7 +86,7 @@ rec {
|
||||||
foldAttrs = op: nul: list_of_attrs:
|
foldAttrs = op: nul: list_of_attrs:
|
||||||
fold (n: a:
|
fold (n: a:
|
||||||
fold (name: o:
|
fold (name: o:
|
||||||
o // (listToAttrs [{inherit name; value = op (getAttr name n) (maybeAttr name nul a); }])
|
o // (listToAttrs [{inherit name; value = op n.${name} (maybeAttr name nul a); }])
|
||||||
) a (attrNames n)
|
) a (attrNames n)
|
||||||
) {} list_of_attrs;
|
) {} list_of_attrs;
|
||||||
|
|
||||||
|
@ -133,7 +132,7 @@ rec {
|
||||||
=> { x = "x-foo"; y = "y-bar"; }
|
=> { x = "x-foo"; y = "y-bar"; }
|
||||||
*/
|
*/
|
||||||
mapAttrs = f: set:
|
mapAttrs = f: set:
|
||||||
listToAttrs (map (attr: { name = attr; value = f attr (getAttr attr set); }) (attrNames set));
|
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set));
|
||||||
|
|
||||||
|
|
||||||
/* Like `mapAttrs', but allows the name of each attribute to be
|
/* Like `mapAttrs', but allows the name of each attribute to be
|
||||||
|
@ -146,7 +145,7 @@ rec {
|
||||||
=> { foo_x = "bar-a"; foo_y = "bar-b"; }
|
=> { foo_x = "bar-a"; foo_y = "bar-b"; }
|
||||||
*/
|
*/
|
||||||
mapAttrs' = f: set:
|
mapAttrs' = f: set:
|
||||||
listToAttrs (map (attr: f attr (getAttr attr set)) (attrNames set));
|
listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
|
||||||
|
|
||||||
|
|
||||||
/* Call a function for each attribute in the given set and return
|
/* Call a function for each attribute in the given set and return
|
||||||
|
@ -158,7 +157,7 @@ rec {
|
||||||
=> [ "xa" "yb" ]
|
=> [ "xa" "yb" ]
|
||||||
*/
|
*/
|
||||||
mapAttrsToList = f: attrs:
|
mapAttrsToList = f: attrs:
|
||||||
map (name: f name (getAttr name attrs)) (attrNames attrs);
|
map (name: f name attrs.${name}) (attrNames attrs);
|
||||||
|
|
||||||
|
|
||||||
/* Like `mapAttrs', except that it recursively applies itself to
|
/* Like `mapAttrs', except that it recursively applies itself to
|
||||||
|
@ -323,7 +322,7 @@ rec {
|
||||||
# override only the attributes that are already present in the old set
|
# override only the attributes that are already present in the old set
|
||||||
# useful for deep-overriding
|
# useful for deep-overriding
|
||||||
overrideExisting = old: new:
|
overrideExisting = old: new:
|
||||||
old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] (getAttr attr old) new)) (attrNames old));
|
old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] old.${attr} new)) (attrNames old));
|
||||||
|
|
||||||
deepSeqAttrs = x: y: deepSeqList (attrValues x) y;
|
deepSeqAttrs = x: y: deepSeqList (attrValues x) y;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
let lib = import ./default.nix;
|
let
|
||||||
inherit (builtins) getAttr attrNames isFunction;
|
lib = import ./default.nix;
|
||||||
|
inherit (builtins) attrNames isFunction;
|
||||||
in
|
in
|
||||||
|
|
||||||
rec {
|
rec {
|
||||||
|
@ -107,10 +107,10 @@ rec {
|
||||||
outputToAttrListElement = outputName:
|
outputToAttrListElement = outputName:
|
||||||
{ name = outputName;
|
{ name = outputName;
|
||||||
value = commonAttrs // {
|
value = commonAttrs // {
|
||||||
inherit (builtins.getAttr outputName drv) outPath drvPath type outputName;
|
inherit (drv.${outputName}) outPath drvPath type outputName;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputsList = map outputToAttrListElement outputs;
|
outputsList = map outputToAttrListElement outputs;
|
||||||
in builtins.getAttr drv.outputName commonAttrs;
|
in commonAttrs.${drv.outputName};
|
||||||
}
|
}
|
||||||
|
|
47
lib/misc.nix
47
lib/misc.nix
|
@ -1,5 +1,5 @@
|
||||||
let lib = import ./default.nix;
|
let lib = import ./default.nix;
|
||||||
inherit (builtins) isFunction hasAttr getAttr head tail isList isAttrs isInt attrNames;
|
inherit (builtins) isFunction head tail isList isAttrs isInt attrNames;
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ rec {
|
||||||
fun = n : x :
|
fun = n : x :
|
||||||
let newArgs = fixed :
|
let newArgs = fixed :
|
||||||
let args = takeFixed fixed;
|
let args = takeFixed fixed;
|
||||||
mergeFun = getAttr n args;
|
mergeFun = args.${n};
|
||||||
in if isAttrs x then (mergeFun args x)
|
in if isAttrs x then (mergeFun args x)
|
||||||
else assert isFunction x;
|
else assert isFunction x;
|
||||||
mergeFun args (x ( args // { inherit fixed; }));
|
mergeFun args (x ( args // { inherit fixed; }));
|
||||||
|
@ -102,15 +102,12 @@ rec {
|
||||||
# }
|
# }
|
||||||
composedArgsAndFun = f: foldArgs defaultMerge f {};
|
composedArgsAndFun = f: foldArgs defaultMerge f {};
|
||||||
|
|
||||||
|
|
||||||
# shortcut for attrByPath ["name"] default attrs
|
|
||||||
maybeAttrNullable = name: default: attrs:
|
|
||||||
if attrs == null then default else
|
|
||||||
if __hasAttr name attrs then (__getAttr name attrs) else default;
|
|
||||||
|
|
||||||
# shortcut for attrByPath ["name"] default attrs
|
# shortcut for attrByPath ["name"] default attrs
|
||||||
maybeAttr = name: default: attrs:
|
maybeAttrNullable = maybeAttr;
|
||||||
if __hasAttr name attrs then (__getAttr name attrs) else default;
|
|
||||||
|
# shortcut for attrByPath ["name"] default attrs
|
||||||
|
maybeAttr = name: default: attrs: attrs.${name} or default;
|
||||||
|
|
||||||
|
|
||||||
# Return the second argument if the first one is true or the empty version
|
# Return the second argument if the first one is true or the empty version
|
||||||
|
@ -233,7 +230,7 @@ rec {
|
||||||
closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);});
|
closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);});
|
||||||
|
|
||||||
# calls a function (f attr value ) for each record item. returns a list
|
# calls a function (f attr value ) for each record item. returns a list
|
||||||
mapAttrsFlatten = f : r : map (attr: f attr (builtins.getAttr attr r) ) (attrNames r);
|
mapAttrsFlatten = f : r : map (attr: f attr r.${attr}) (attrNames r);
|
||||||
|
|
||||||
# attribute set containing one attribute
|
# attribute set containing one attribute
|
||||||
nvs = name : value : listToAttrs [ (nameValuePair name value) ];
|
nvs = name : value : listToAttrs [ (nameValuePair name value) ];
|
||||||
|
@ -250,10 +247,10 @@ rec {
|
||||||
# merge attributes with custom function handling the case that the attribute
|
# merge attributes with custom function handling the case that the attribute
|
||||||
# exists in both sets
|
# exists in both sets
|
||||||
mergeAttrsWithFunc = f : set1 : set2 :
|
mergeAttrsWithFunc = f : set1 : set2 :
|
||||||
fold (n: set : if (__hasAttr n set)
|
fold (n: set : if set ? ${n}
|
||||||
then setAttr set n (f (__getAttr n set) (__getAttr n set2))
|
then setAttr set n (f set.${n} set2.${n})
|
||||||
else set )
|
else set )
|
||||||
(set2 // set1) (__attrNames set2);
|
(set2 // set1) (attrNames set2);
|
||||||
|
|
||||||
# merging two attribute set concatenating the values of same attribute names
|
# merging two attribute set concatenating the values of same attribute names
|
||||||
# eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
|
# eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
|
||||||
|
@ -270,15 +267,15 @@ rec {
|
||||||
overrideSnd ? [ "buildPhase" ]
|
overrideSnd ? [ "buildPhase" ]
|
||||||
} : attrs1 : attrs2 :
|
} : attrs1 : attrs2 :
|
||||||
fold (n: set :
|
fold (n: set :
|
||||||
setAttr set n ( if (__hasAttr n set)
|
setAttr set n ( if set ? ${n}
|
||||||
then # merge
|
then # merge
|
||||||
if elem n mergeLists # attribute contains list, merge them by concatenating
|
if elem n mergeLists # attribute contains list, merge them by concatenating
|
||||||
then (__getAttr n attrs2) ++ (__getAttr n attrs1)
|
then attrs2.${n} ++ attrs1.${n}
|
||||||
else if elem n overrideSnd
|
else if elem n overrideSnd
|
||||||
then __getAttr n attrs1
|
then attrs1.${n}
|
||||||
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
|
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
|
||||||
else __getAttr n attrs2 # add attribute not existing in attr1
|
else attrs2.${n} # add attribute not existing in attr1
|
||||||
)) attrs1 (__attrNames attrs2);
|
)) attrs1 (attrNames attrs2);
|
||||||
|
|
||||||
|
|
||||||
# example usage:
|
# example usage:
|
||||||
|
@ -300,14 +297,14 @@ rec {
|
||||||
fold lib.mergeAttrs {} [
|
fold lib.mergeAttrs {} [
|
||||||
x y
|
x y
|
||||||
(mapAttrs ( a : v : # merge special names using given functions
|
(mapAttrs ( a : v : # merge special names using given functions
|
||||||
if (hasAttr a x)
|
if x ? ${a}
|
||||||
then if (hasAttr a y)
|
then if y ? ${a}
|
||||||
then v (getAttr a x) (getAttr a y) # both have attr, use merge func
|
then v x.${a} y.${a} # both have attr, use merge func
|
||||||
else (getAttr a x) # only x has attr
|
else x.${a} # only x has attr
|
||||||
else (getAttr a y) # only y has attr)
|
else y.${a} # only y has attr)
|
||||||
) (removeAttrs mergeAttrBy2
|
) (removeAttrs mergeAttrBy2
|
||||||
# don't merge attrs which are neither in x nor y
|
# don't merge attrs which are neither in x nor y
|
||||||
(filter (a : (! hasAttr a x) && (! hasAttr a y) )
|
(filter (a: ! x ? ${a} && ! y ? ${a})
|
||||||
(attrNames mergeAttrBy2))
|
(attrNames mergeAttrBy2))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -403,7 +400,7 @@ rec {
|
||||||
// args2.cfg;
|
// args2.cfg;
|
||||||
opts = attrValues (mapAttrs (a : v :
|
opts = attrValues (mapAttrs (a : v :
|
||||||
let v2 = if v ? set || v ? unset then v else { set = v; };
|
let v2 = if v ? set || v ? unset then v else { set = v; };
|
||||||
n = if (getAttr (flagName a) cfgWithDefaults) then "set" else "unset";
|
n = if cfgWithDefaults.${flagName a} then "set" else "unset";
|
||||||
attr = maybeAttr n {} v2; in
|
attr = maybeAttr n {} v2; in
|
||||||
if (maybeAttr "assertion" true attr)
|
if (maybeAttr "assertion" true attr)
|
||||||
then attr
|
then attr
|
||||||
|
|
|
@ -30,7 +30,7 @@ rec {
|
||||||
if check && set ? _definedNames then
|
if check && set ? _definedNames then
|
||||||
fold (m: res:
|
fold (m: res:
|
||||||
fold (name: res:
|
fold (name: res:
|
||||||
if hasAttr name set then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.")
|
if set ? ${name} then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.")
|
||||||
res m.names)
|
res m.names)
|
||||||
res set._definedNames
|
res set._definedNames
|
||||||
else
|
else
|
||||||
|
@ -94,22 +94,22 @@ rec {
|
||||||
loc = prefix ++ [name];
|
loc = prefix ++ [name];
|
||||||
# Get all submodules that declare ‘name’.
|
# Get all submodules that declare ‘name’.
|
||||||
decls = concatLists (map (m:
|
decls = concatLists (map (m:
|
||||||
if hasAttr name m.options
|
if m.options ? ${name}
|
||||||
then [ { inherit (m) file; options = getAttr name m.options; } ]
|
then [ { inherit (m) file; options = m.options.${name}; } ]
|
||||||
else []
|
else []
|
||||||
) options);
|
) options);
|
||||||
# Get all submodules that define ‘name’.
|
# Get all submodules that define ‘name’.
|
||||||
defns = concatLists (map (m:
|
defns = concatLists (map (m:
|
||||||
if hasAttr name m.config
|
if m.config ? ${name}
|
||||||
then map (config: { inherit (m) file; inherit config; })
|
then map (config: { inherit (m) file; inherit config; })
|
||||||
(pushDownProperties (getAttr name m.config))
|
(pushDownProperties m.config.${name})
|
||||||
else []
|
else []
|
||||||
) configs);
|
) configs);
|
||||||
nrOptions = count (m: isOption m.options) decls;
|
nrOptions = count (m: isOption m.options) decls;
|
||||||
# Process mkMerge and mkIf properties.
|
# Process mkMerge and mkIf properties.
|
||||||
defns' = concatMap (m:
|
defns' = concatMap (m:
|
||||||
if hasAttr name m.config
|
if m.config ? ${name}
|
||||||
then map (m': { inherit (m) file; value = m'; }) (dischargeProperties (getAttr name m.config))
|
then map (m': { inherit (m) file; value = m'; }) (dischargeProperties m.config.${name})
|
||||||
else []
|
else []
|
||||||
) configs;
|
) configs;
|
||||||
in
|
in
|
||||||
|
|
|
@ -62,8 +62,8 @@ rec {
|
||||||
in { result = x.result ++ [entry.text] ++ y.result;
|
in { result = x.result ++ [entry.text] ++ y.result;
|
||||||
done = y.done;
|
done = y.done;
|
||||||
}
|
}
|
||||||
else if hasAttr entry done then f done (tail todo)
|
else if done ? ${entry} then f done (tail todo)
|
||||||
else f (done // listToAttrs [{name = entry; value = 1;}]) ([(builtins.getAttr entry predefined)] ++ tail todo);
|
else f (done // listToAttrs [{name = entry; value = 1;}]) ([predefined.${entry}] ++ tail todo);
|
||||||
in (f {} arg).result;
|
in (f {} arg).result;
|
||||||
|
|
||||||
textClosureMap = f: predefined: names:
|
textClosureMap = f: predefined: names:
|
||||||
|
|
|
@ -399,8 +399,8 @@ in
|
||||||
services.xserver.drivers = flip concatMap cfg.videoDrivers (name:
|
services.xserver.drivers = flip concatMap cfg.videoDrivers (name:
|
||||||
let driver =
|
let driver =
|
||||||
attrByPath [name]
|
attrByPath [name]
|
||||||
(if (hasAttr ("xf86video" + name) xorg)
|
(if xorg ? ${"xf86video" + name}
|
||||||
then { modules = [(getAttr ("xf86video" + name) xorg) ]; }
|
then { modules = [xorg.${"xf86video" + name}]; }
|
||||||
else null)
|
else null)
|
||||||
knownVideoDrivers;
|
knownVideoDrivers;
|
||||||
in optional (driver != null) ({ inherit name; driverName = name; } // driver));
|
in optional (driver != null) ({ inherit name; driverName = name; } // driver));
|
||||||
|
|
|
@ -6,8 +6,8 @@ let
|
||||||
|
|
||||||
checkService = v:
|
checkService = v:
|
||||||
let assertValueOneOf = name: values: attr:
|
let assertValueOneOf = name: values: attr:
|
||||||
let val = getAttr name attr;
|
let val = attr.${name};
|
||||||
in optional ( hasAttr name attr && !elem val values) "Systemd service field `${name}' cannot have value `${val}'.";
|
in optional (attr ? ${name} && !elem val values) "Systemd service field `${name}' cannot have value `${val}'.";
|
||||||
checkType = assertValueOneOf "Type" ["simple" "forking" "oneshot" "dbus" "notify" "idle"];
|
checkType = assertValueOneOf "Type" ["simple" "forking" "oneshot" "dbus" "notify" "idle"];
|
||||||
checkRestart = assertValueOneOf "Restart" ["no" "on-success" "on-failure" "on-abort" "always"];
|
checkRestart = assertValueOneOf "Restart" ["no" "on-success" "on-failure" "on-abort" "always"];
|
||||||
errors = concatMap (c: c v) [checkType checkRestart];
|
errors = concatMap (c: c v) [checkType checkRestart];
|
||||||
|
|
|
@ -321,7 +321,7 @@ let
|
||||||
[Service]
|
[Service]
|
||||||
${let env = cfg.globalEnvironment // def.environment;
|
${let env = cfg.globalEnvironment // def.environment;
|
||||||
in concatMapStrings (n:
|
in concatMapStrings (n:
|
||||||
let s = "Environment=\"${n}=${getAttr n env}\"\n";
|
let s = "Environment=\"${n}=${env.${n}}\"\n";
|
||||||
in if stringLength s >= 2048 then throw "The value of the environment variable ‘${n}’ in systemd service ‘${name}.service’ is too long." else s) (attrNames env)}
|
in if stringLength s >= 2048 then throw "The value of the environment variable ‘${n}’ in systemd service ‘${name}.service’ is too long." else s) (attrNames env)}
|
||||||
${if def.reloadIfChanged then ''
|
${if def.reloadIfChanged then ''
|
||||||
X-ReloadIfChanged=true
|
X-ReloadIfChanged=true
|
||||||
|
|
Loading…
Reference in New Issue