From 97220c973fdc6d3cfa02fe597c4301e87177603c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Sun, 5 Oct 2014 00:03:52 +0200 Subject: [PATCH] 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. --- lib/attrsets.nix | 21 ++++----- lib/customisation.nix | 10 ++-- lib/misc.nix | 47 +++++++++---------- lib/modules.nix | 14 +++--- lib/strings-with-deps.nix | 4 +- nixos/modules/services/x11/xserver.nix | 4 +- .../system/boot/systemd-unit-options.nix | 4 +- nixos/modules/system/boot/systemd.nix | 2 +- 8 files changed, 51 insertions(+), 55 deletions(-) diff --git a/lib/attrsets.nix b/lib/attrsets.nix index d22131c47951..3615328b1924 100644 --- a/lib/attrsets.nix +++ b/lib/attrsets.nix @@ -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; } diff --git a/lib/customisation.nix b/lib/customisation.nix index bfa61169efb1..90a0c65058d0 100644 --- a/lib/customisation.nix +++ b/lib/customisation.nix @@ -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}; } diff --git a/lib/misc.nix b/lib/misc.nix index c128b9af9d8c..fd20ce25010c 100644 --- a/lib/misc.nix +++ b/lib/misc.nix @@ -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 diff --git a/lib/modules.nix b/lib/modules.nix index 5ef7b4bb090e..8af08522051f 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -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 diff --git a/lib/strings-with-deps.nix b/lib/strings-with-deps.nix index 3ad3e5991506..bdcc25cbd20c 100644 --- a/lib/strings-with-deps.nix +++ b/lib/strings-with-deps.nix @@ -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: diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index c08afe2041f4..1ce8de23c16d 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -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)); diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix index 48c3564ba078..07f3cb9e952c 100644 --- a/nixos/modules/system/boot/systemd-unit-options.nix +++ b/nixos/modules/system/boot/systemd-unit-options.nix @@ -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]; diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index f2f7989ab4de..d0fe69c15dd5 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -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