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:
Eelco Dolstra 2014-10-05 00:03:52 +02:00
parent 0e120dc68f
commit 97220c973f
8 changed files with 51 additions and 55 deletions

View file

@ -20,8 +20,8 @@ rec {
let attr = head attrPath;
in
if attrPath == [] then e
else if hasAttr attr e
then attrByPath (tail attrPath) default (getAttr attr e)
else if e ? ${attr}
then attrByPath (tail attrPath) default e.${attr}
else default;
@ -44,8 +44,7 @@ rec {
attrVals ["a" "b" "c"] as
=> [as.a as.b as.c]
*/
attrVals = nameList: set:
map (x: getAttr x set) nameList;
attrVals = nameList: set: map (x: set.${x}) nameList;
/* Return the values of all attributes in the given set, sorted by
@ -66,7 +65,7 @@ rec {
=> [1 2]
*/
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
@ -77,7 +76,7 @@ rec {
=> { foo = 1; }
*/
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:
@ -87,7 +86,7 @@ rec {
foldAttrs = op: nul: list_of_attrs:
fold (n: a:
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)
) {} list_of_attrs;
@ -133,7 +132,7 @@ rec {
=> { x = "x-foo"; y = "y-bar"; }
*/
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
@ -146,7 +145,7 @@ rec {
=> { foo_x = "bar-a"; foo_y = "bar-b"; }
*/
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
@ -158,7 +157,7 @@ rec {
=> [ "xa" "yb" ]
*/
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
@ -323,7 +322,7 @@ rec {
# override only the attributes that are already present in the old set
# useful for deep-overriding
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;
}

View file

@ -1,6 +1,6 @@
let lib = import ./default.nix;
inherit (builtins) getAttr attrNames isFunction;
let
lib = import ./default.nix;
inherit (builtins) attrNames isFunction;
in
rec {
@ -107,10 +107,10 @@ rec {
outputToAttrListElement = outputName:
{ name = outputName;
value = commonAttrs // {
inherit (builtins.getAttr outputName drv) outPath drvPath type outputName;
inherit (drv.${outputName}) outPath drvPath type outputName;
};
};
outputsList = map outputToAttrListElement outputs;
in builtins.getAttr drv.outputName commonAttrs;
in commonAttrs.${drv.outputName};
}

View file

@ -1,5 +1,5 @@
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
@ -61,7 +61,7 @@ rec {
fun = n : x :
let newArgs = fixed :
let args = takeFixed fixed;
mergeFun = getAttr n args;
mergeFun = args.${n};
in if isAttrs x then (mergeFun args x)
else assert isFunction x;
mergeFun args (x ( args // { inherit fixed; }));
@ -102,15 +102,12 @@ rec {
# }
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
maybeAttr = name: default: attrs:
if __hasAttr name attrs then (__getAttr name attrs) else default;
maybeAttrNullable = maybeAttr;
# 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
@ -233,7 +230,7 @@ rec {
closePropagation = list: (uniqList {inputList = (innerClosePropagation [] 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
nvs = name : value : listToAttrs [ (nameValuePair name value) ];
@ -250,10 +247,10 @@ rec {
# merge attributes with custom function handling the case that the attribute
# exists in both sets
mergeAttrsWithFunc = f : set1 : set2 :
fold (n: set : if (__hasAttr n set)
then setAttr set n (f (__getAttr n set) (__getAttr n set2))
fold (n: set : if set ? ${n}
then setAttr set n (f set.${n} set2.${n})
else set )
(set2 // set1) (__attrNames set2);
(set2 // set1) (attrNames set2);
# merging two attribute set concatenating the values of same attribute names
# eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
@ -270,15 +267,15 @@ rec {
overrideSnd ? [ "buildPhase" ]
} : attrs1 : attrs2 :
fold (n: set :
setAttr set n ( if (__hasAttr n set)
setAttr set n ( if set ? ${n}
then # merge
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
then __getAttr n attrs1
then attrs1.${n}
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
else __getAttr n attrs2 # add attribute not existing in attr1
)) attrs1 (__attrNames attrs2);
else attrs2.${n} # add attribute not existing in attr1
)) attrs1 (attrNames attrs2);
# example usage:
@ -300,14 +297,14 @@ rec {
fold lib.mergeAttrs {} [
x y
(mapAttrs ( a : v : # merge special names using given functions
if (hasAttr a x)
then if (hasAttr a y)
then v (getAttr a x) (getAttr a y) # both have attr, use merge func
else (getAttr a x) # only x has attr
else (getAttr a y) # only y has attr)
if x ? ${a}
then if y ? ${a}
then v x.${a} y.${a} # both have attr, use merge func
else x.${a} # only x has attr
else y.${a} # only y has attr)
) (removeAttrs mergeAttrBy2
# 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))
)
)
@ -403,7 +400,7 @@ rec {
// args2.cfg;
opts = attrValues (mapAttrs (a : 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
if (maybeAttr "assertion" true attr)
then attr

View file

@ -30,7 +30,7 @@ rec {
if check && set ? _definedNames then
fold (m: 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 set._definedNames
else
@ -94,22 +94,22 @@ rec {
loc = prefix ++ [name];
# Get all submodules that declare name.
decls = concatLists (map (m:
if hasAttr name m.options
then [ { inherit (m) file; options = getAttr name m.options; } ]
if m.options ? ${name}
then [ { inherit (m) file; options = m.options.${name}; } ]
else []
) options);
# Get all submodules that define name.
defns = concatLists (map (m:
if hasAttr name m.config
if m.config ? ${name}
then map (config: { inherit (m) file; inherit config; })
(pushDownProperties (getAttr name m.config))
(pushDownProperties m.config.${name})
else []
) configs);
nrOptions = count (m: isOption m.options) decls;
# Process mkMerge and mkIf properties.
defns' = concatMap (m:
if hasAttr name m.config
then map (m': { inherit (m) file; value = m'; }) (dischargeProperties (getAttr name m.config))
if m.config ? ${name}
then map (m': { inherit (m) file; value = m'; }) (dischargeProperties m.config.${name})
else []
) configs;
in

View file

@ -62,8 +62,8 @@ rec {
in { result = x.result ++ [entry.text] ++ y.result;
done = y.done;
}
else if hasAttr entry done then f done (tail todo)
else f (done // listToAttrs [{name = entry; value = 1;}]) ([(builtins.getAttr entry predefined)] ++ tail todo);
else if done ? ${entry} then f done (tail todo)
else f (done // listToAttrs [{name = entry; value = 1;}]) ([predefined.${entry}] ++ tail todo);
in (f {} arg).result;
textClosureMap = f: predefined: names:

View file

@ -399,8 +399,8 @@ in
services.xserver.drivers = flip concatMap cfg.videoDrivers (name:
let driver =
attrByPath [name]
(if (hasAttr ("xf86video" + name) xorg)
then { modules = [(getAttr ("xf86video" + name) xorg) ]; }
(if xorg ? ${"xf86video" + name}
then { modules = [xorg.${"xf86video" + name}]; }
else null)
knownVideoDrivers;
in optional (driver != null) ({ inherit name; driverName = name; } // driver));

View file

@ -6,8 +6,8 @@ let
checkService = v:
let assertValueOneOf = name: values: attr:
let val = getAttr name attr;
in optional ( hasAttr name attr && !elem val values) "Systemd service field `${name}' cannot have value `${val}'.";
let val = attr.${name};
in optional (attr ? ${name} && !elem val values) "Systemd service field `${name}' cannot have value `${val}'.";
checkType = assertValueOneOf "Type" ["simple" "forking" "oneshot" "dbus" "notify" "idle"];
checkRestart = assertValueOneOf "Restart" ["no" "on-success" "on-failure" "on-abort" "always"];
errors = concatMap (c: c v) [checkType checkRestart];

View file

@ -321,7 +321,7 @@ let
[Service]
${let env = cfg.globalEnvironment // def.environment;
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)}
${if def.reloadIfChanged then ''
X-ReloadIfChanged=true