summary refs log tree commit diff
diff options
context:
space:
mode:
authorDanylo Hlynskyi <abcz2.uprola@gmail.com>2019-08-18 18:47:57 +0300
committerGitHub <noreply@github.com>2019-08-18 18:47:57 +0300
commitd09b4e3c87e744f90f4d44eb2b2f3fa92912b7c3 (patch)
tree0080515df4c61351ef9efd573e867a768e05b0dc
parenta2ea2a1945df9f164d1bdfffc1efbefd2f139b6b (diff)
parentd80cd26ff981f1c4be96b82757811b21f280f1a6 (diff)
downloadnixpkgs-d09b4e3c87e744f90f4d44eb2b2f3fa92912b7c3.tar
nixpkgs-d09b4e3c87e744f90f4d44eb2b2f3fa92912b7c3.tar.gz
nixpkgs-d09b4e3c87e744f90f4d44eb2b2f3fa92912b7c3.tar.bz2
nixpkgs-d09b4e3c87e744f90f4d44eb2b2f3fa92912b7c3.tar.lz
nixpkgs-d09b4e3c87e744f90f4d44eb2b2f3fa92912b7c3.tar.xz
nixpkgs-d09b4e3c87e744f90f4d44eb2b2f3fa92912b7c3.tar.zst
nixpkgs-d09b4e3c87e744f90f4d44eb2b2f3fa92912b7c3.zip
lib: introduce `forEach` = flip map (#64723)
* lib: introduce `foreach` = flip map

The main purpose is to bring attention to `flip map`, which improves
code readablity. It is useful when ad-hoc anonymous function
grows two or more lines in `map` application:

```
      map (lcfg:
        let port = lcfg.port;
            portStr = if port != defaultPort then ":${toString port}" else "";
            scheme = if cfg.enableSSL then "https" else "http";
        in "${scheme}://cfg.hostName${portStr}"
      ) (getListen cfg);
```
Compare this to `foreach`-style:
```
      foreach (getListen cfg) (lcfg:
        let port = lcfg.port;
            portStr = if port != defaultPort then ":${toString port}" else "";
            scheme = if cfg.enableSSL then "https" else "http";
        in "${scheme}://cfg.hostName${portStr}"
      );
```
This is similar to Haskell's `for` (http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Traversable.html#v:for)

* mass replace "flip map -> foreach"

See `foreach`-introduction commit.
```
rg 'flip map ' --files-with-matches | xargs sed -i 's/flip map /foreach /g'
```

* Revert "mass replace "flip map -> foreach""

This reverts commit 3b0534310c89d04fc3a9c5714b5a4d0f9fb0efca.

* mass replace "flip map -> forEach"

See `forEach`-introduction commit.
```
rg 'flip map ' --files-with-matches | xargs sed -i 's/flip map /forEach /g'
```

* rename foreach -> forEach

* and one more place

* add release notes
-rw-r--r--lib/default.nix2
-rw-r--r--lib/lists.nix13
-rw-r--r--nixos/doc/manual/release-notes/rl-1909.xml12
-rw-r--r--nixos/lib/build-vms.nix6
-rw-r--r--nixos/maintainers/option-usages.nix2
-rw-r--r--nixos/modules/rename.nix2
-rw-r--r--nixos/modules/services/monitoring/ups.nix2
-rw-r--r--nixos/modules/services/networking/consul.nix2
-rw-r--r--nixos/modules/services/networking/hylafax/systemd.nix2
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix2
-rw-r--r--nixos/modules/services/x11/xautolock.nix2
-rw-r--r--nixos/modules/services/x11/xserver.nix2
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix2
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix8
-rw-r--r--nixos/modules/tasks/network-interfaces.nix12
-rw-r--r--nixos/tests/networking.nix2
-rw-r--r--pkgs/applications/networking/irc/weechat/wrapper.nix2
-rw-r--r--pkgs/applications/networking/remote/citrix-receiver/default.nix2
-rw-r--r--pkgs/applications/networking/remote/citrix-workspace/default.nix2
-rw-r--r--pkgs/tools/inputmethods/ibus-engines/ibus-typing-booster/wrapper.nix2
20 files changed, 53 insertions, 28 deletions
diff --git a/lib/default.nix b/lib/default.nix
index 3efaaf0f8f9..18d2dfae1e1 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -71,7 +71,7 @@ let
       zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
       recursiveUpdate matchAttrs overrideExisting getOutput getBin
       getLib getDev chooseDevOutputs zipWithNames zip;
-    inherit (lists) singleton foldr fold foldl foldl' imap0 imap1
+    inherit (lists) singleton forEach foldr fold foldl foldl' imap0 imap1
       concatMap flatten remove findSingle findFirst any all count
       optional optionals toList range partition zipListsWith zipLists
       reverseList listDfs toposort sort naturalSort compareLists take
diff --git a/lib/lists.nix b/lib/lists.nix
index 30d87ece664..e4fcf959b60 100644
--- a/lib/lists.nix
+++ b/lib/lists.nix
@@ -21,6 +21,19 @@ rec {
   */
   singleton = x: [x];
 
+  /*  Apply the function to each element in the list. Same as `map`, but arguments
+      flipped.
+
+      Type: forEach :: [a] -> (a -> b) -> [b]
+
+      Example:
+        forEach [ 1 2 ] (x:
+          toString x
+        )
+        => [ "1" "2" ]
+  */
+  forEach = xs: f: map f xs;
+
   /* “right fold” a binary function `op` between successive elements of
      `list` with `nul' as the starting value, i.e.,
      `foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))`.
diff --git a/nixos/doc/manual/release-notes/rl-1909.xml b/nixos/doc/manual/release-notes/rl-1909.xml
index e0f71aadaba..ca2f26ec4a8 100644
--- a/nixos/doc/manual/release-notes/rl-1909.xml
+++ b/nixos/doc/manual/release-notes/rl-1909.xml
@@ -424,6 +424,18 @@
      installer after creating <literal>/var/lib/nextcloud</literal>.
     </para>
    </listitem>
+   <listitem>
+    <para>
+     There exists now <literal>lib.forEach</literal>, which is like <literal>map</literal>, but with
+     arguments flipped. When mapping function body spans many lines (or has nested
+     <literal>map</literal>s), it is often hard to follow which list is modified.
+    </para>
+    <para>
+     Previous solution to this problem was either to use <literal>lib.flip map</literal>
+     idiom or extract that anonymous mapping function to a named one. Both can still be used
+     but <literal>lib.forEach</literal> is preferred over <literal>lib.flip map</literal>.
+    </para>
+   </listitem>
   </itemizedlist>
  </section>
 </section>
diff --git a/nixos/lib/build-vms.nix b/nixos/lib/build-vms.nix
index b622a4d59e8..1bad63b9194 100644
--- a/nixos/lib/build-vms.nix
+++ b/nixos/lib/build-vms.nix
@@ -54,11 +54,11 @@ rec {
 
       machinesNumbered = zipLists machines (range 1 254);
 
-      nodes_ = flip map machinesNumbered (m: nameValuePair m.fst
+      nodes_ = forEach machinesNumbered (m: nameValuePair m.fst
         [ ( { config, nodes, ... }:
             let
               interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255);
-              interfaces = flip map interfacesNumbered ({ fst, snd }:
+              interfaces = forEach interfacesNumbered ({ fst, snd }:
                 nameValuePair "eth${toString snd}" { ipv4.addresses =
                   [ { address = "192.168.${toString fst}.${toString m.snd}";
                       prefixLength = 24;
@@ -88,7 +88,7 @@ rec {
                          "${config.networking.hostName}\n"));
 
                   virtualisation.qemu.options =
-                    flip map interfacesNumbered
+                    forEach interfacesNumbered
                       ({ fst, snd }: qemuNICFlags snd fst m.snd);
                 };
             }
diff --git a/nixos/maintainers/option-usages.nix b/nixos/maintainers/option-usages.nix
index a67a0ab960e..11247666ecd 100644
--- a/nixos/maintainers/option-usages.nix
+++ b/nixos/maintainers/option-usages.nix
@@ -102,7 +102,7 @@ let
       # builtins multiply by 4 the memory usage and the time used to compute
       # each options.
       tryCollectOptions = moduleResult:
-        flip map (excludeOptions (collect isOption moduleResult)) (opt:
+        forEach (excludeOptions (collect isOption moduleResult)) (opt:
           { name = showOption opt.loc; } // builtins.tryEval (strict opt.value));
      in
        keepNames (
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 5c08a25c128..3ea139fc5ce 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -276,7 +276,7 @@ with lib;
           throw "services.redshift.longitude is set to null, you can remove this"
           else builtins.fromJSON value))
 
-  ] ++ (flip map [ "blackboxExporter" "collectdExporter" "fritzboxExporter"
+  ] ++ (forEach [ "blackboxExporter" "collectdExporter" "fritzboxExporter"
                    "jsonExporter" "minioExporter" "nginxExporter" "nodeExporter"
                    "snmpExporter" "unifiExporter" "varnishExporter" ]
        (opt: mkRemovedOptionModule [ "services" "prometheus" "${opt}" ] ''
diff --git a/nixos/modules/services/monitoring/ups.nix b/nixos/modules/services/monitoring/ups.nix
index bc755612fd9..429b40227d4 100644
--- a/nixos/modules/services/monitoring/ups.nix
+++ b/nixos/modules/services/monitoring/ups.nix
@@ -225,7 +225,7 @@ in
         ''
           maxstartdelay = ${toString cfg.maxStartDelay}
 
-          ${flip concatStringsSep (flip map (attrValues cfg.ups) (ups: ups.summary)) "
+          ${flip concatStringsSep (forEach (attrValues cfg.ups) (ups: ups.summary)) "
 
           "}
         '';
diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix
index 3a92a883fbf..f080f12eacc 100644
--- a/nixos/modules/services/networking/consul.nix
+++ b/nixos/modules/services/networking/consul.nix
@@ -15,7 +15,7 @@ let
     ++ cfg.extraConfigFiles;
 
   devices = attrValues (filterAttrs (_: i: i != null) cfg.interface);
-  systemdDevices = flip map devices
+  systemdDevices = forEach devices
     (i: "sys-subsystem-net-devices-${utils.escapeSystemdPath i}.device");
 in
 {
diff --git a/nixos/modules/services/networking/hylafax/systemd.nix b/nixos/modules/services/networking/hylafax/systemd.nix
index ef177e4be34..0c6602e7f8a 100644
--- a/nixos/modules/services/networking/hylafax/systemd.nix
+++ b/nixos/modules/services/networking/hylafax/systemd.nix
@@ -7,7 +7,7 @@ let
   inherit (lib) concatStringsSep optionalString;
 
   cfg = config.services.hylafax;
-  mapModems = lib.flip map (lib.attrValues cfg.modems);
+  mapModems = lib.forEach (lib.attrValues cfg.modems);
 
   mkConfigFile = name: conf:
     # creates hylafax config file,
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 0f9d2420903..91fc7d72bc6 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -502,7 +502,7 @@ in
 
     assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;
                     message = "cannot enable X11 forwarding without setting xauth location";}]
-      ++ flip map cfg.listenAddresses ({ addr, ... }: {
+      ++ forEach cfg.listenAddresses ({ addr, ... }: {
         assertion = addr != null;
         message = "addr must be specified in each listenAddresses entry";
       });
diff --git a/nixos/modules/services/x11/xautolock.nix b/nixos/modules/services/x11/xautolock.nix
index cbe000058dc..10eef8aefbc 100644
--- a/nixos/modules/services/x11/xautolock.nix
+++ b/nixos/modules/services/x11/xautolock.nix
@@ -129,7 +129,7 @@ in
           assertion = cfg.killer != null -> cfg.killtime >= 10;
           message = "killtime has to be at least 10 minutes according to `man xautolock`";
         }
-      ] ++ (lib.flip map [ "locker" "notifier" "nowlocker" "killer" ]
+      ] ++ (lib.forEach [ "locker" "notifier" "nowlocker" "killer" ]
         (option:
         {
           assertion = cfg."${option}" != null -> builtins.substring 0 1 cfg."${option}" == "/";
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 7ffe1c12561..c94a0643831 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -78,7 +78,7 @@ let
   in imap1 mkHead cfg.xrandrHeads;
 
   xrandrDeviceSection = let
-    monitors = flip map xrandrHeads (h: ''
+    monitors = forEach xrandrHeads (h: ''
       Option "monitor-${h.config.output}" "${h.name}"
     '');
     # First option is indented through the space in the config but any
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index 4e4d14985b0..eca9dad6422 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -684,7 +684,7 @@ in
           assertion = if args.efiSysMountPoint == null then true else hasPrefix "/" args.efiSysMountPoint;
           message = "EFI paths must be absolute, not ${args.efiSysMountPoint}";
         }
-      ] ++ flip map args.devices (device: {
+      ] ++ forEach args.devices (device: {
         assertion = device == "nodev" || hasPrefix "/" device;
         message = "GRUB devices must be absolute paths, not ${device} in ${args.path}";
       }));
diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix
index 857aaf1e6e3..fbca54978e5 100644
--- a/nixos/modules/tasks/network-interfaces-systemd.nix
+++ b/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -74,7 +74,7 @@ in
         enable = true;
         networks."99-main" = genericNetwork mkDefault;
       }
-      (mkMerge (flip map interfaces (i: {
+      (mkMerge (forEach interfaces (i: {
         netdevs = mkIf i.virtual ({
           "40-${i.name}" = {
             netdevConfig = {
@@ -90,7 +90,7 @@ in
           name = mkDefault i.name;
           DHCP = mkForce (dhcpStr
             (if i.useDHCP != null then i.useDHCP else cfg.useDHCP && interfaceIps i == [ ]));
-          address = flip map (interfaceIps i)
+          address = forEach (interfaceIps i)
             (ip: "${ip.address}/${toString ip.prefixLength}");
           networkConfig.IPv6PrivacyExtensions = "kernel";
         } ];
@@ -102,7 +102,7 @@ in
             Kind = "bridge";
           };
         };
-        networks = listToAttrs (flip map bridge.interfaces (bi:
+        networks = listToAttrs (forEach bridge.interfaces (bi:
           nameValuePair "40-${bi}" (mkMerge [ (genericNetwork (mkOverride 999)) {
             DHCP = mkOverride 0 (dhcpStr false);
             networkConfig.Bridge = name;
@@ -173,7 +173,7 @@ in
 
         };
 
-        networks = listToAttrs (flip map bond.interfaces (bi:
+        networks = listToAttrs (forEach bond.interfaces (bi:
           nameValuePair "40-${bi}" (mkMerge [ (genericNetwork (mkOverride 999)) {
             DHCP = mkOverride 0 (dhcpStr false);
             networkConfig.Bond = name;
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index c75d7cbc408..5ac753c92a7 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -926,7 +926,7 @@ in
     warnings = concatMap (i: i.warnings) interfaces;
 
     assertions =
-      (flip map interfaces (i: {
+      (forEach interfaces (i: {
         # With the linux kernel, interface name length is limited by IFNAMSIZ
         # to 16 bytes, including the trailing null byte.
         # See include/linux/if.h in the kernel sources
@@ -934,12 +934,12 @@ in
         message = ''
           The name of networking.interfaces."${i.name}" is too long, it needs to be less than 16 characters.
         '';
-      })) ++ (flip map slaveIfs (i: {
+      })) ++ (forEach slaveIfs (i: {
         assertion = i.ipv4.addresses == [ ] && i.ipv6.addresses == [ ];
         message = ''
           The networking.interfaces."${i.name}" must not have any defined ips when it is a slave.
         '';
-      })) ++ (flip map interfaces (i: {
+      })) ++ (forEach interfaces (i: {
         assertion = i.preferTempAddress -> cfg.enableIPv6;
         message = ''
           Temporary addresses are only needed when IPv6 is enabled.
@@ -967,8 +967,8 @@ in
       "net.ipv6.conf.default.disable_ipv6" = mkDefault (!cfg.enableIPv6);
       "net.ipv6.conf.all.forwarding" = mkDefault (any (i: i.proxyARP) interfaces);
     } // listToAttrs (flip concatMap (filter (i: i.proxyARP) interfaces)
-        (i: flip map [ "4" "6" ] (v: nameValuePair "net.ipv${v}.conf.${i.name}.proxy_arp" true)))
-      // listToAttrs (flip map (filter (i: i.preferTempAddress) interfaces)
+        (i: forEach [ "4" "6" ] (v: nameValuePair "net.ipv${v}.conf.${i.name}.proxy_arp" true)))
+      // listToAttrs (forEach (filter (i: i.preferTempAddress) interfaces)
         (i: nameValuePair "net.ipv6.conf.${i.name}.use_tempaddr" 2));
 
     # Capabilities won't work unless we have at-least a 4.3 Linux
@@ -1050,7 +1050,7 @@ in
           ${cfg.localCommands}
         '';
       };
-    } // (listToAttrs (flip map interfaces (i:
+    } // (listToAttrs (forEach interfaces (i:
       let
         deviceDependency = if (config.boot.isContainer || i.name == "lo")
           then []
diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix
index 949d946bdc4..6ce64dcebea 100644
--- a/nixos/tests/networking.nix
+++ b/nixos/tests/networking.nix
@@ -21,7 +21,7 @@ let
         useNetworkd = networkd;
         firewall.checkReversePath = true;
         firewall.allowedUDPPorts = [ 547 ];
-        interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n:
+        interfaces = mkOverride 0 (listToAttrs (forEach vlanIfs (n:
           nameValuePair "eth${toString n}" {
             ipv4.addresses = [ { address = "192.168.${toString n}.1"; prefixLength = 24; } ];
             ipv6.addresses = [ { address = "fd00:1234:5678:${toString n}::1"; prefixLength = 64; } ];
diff --git a/pkgs/applications/networking/irc/weechat/wrapper.nix b/pkgs/applications/networking/irc/weechat/wrapper.nix
index c773aecf289..e6fa95488e1 100644
--- a/pkgs/applications/networking/irc/weechat/wrapper.nix
+++ b/pkgs/applications/networking/irc/weechat/wrapper.nix
@@ -56,7 +56,7 @@ let
     init = let
       init = builtins.replaceStrings [ "\n" ] [ ";" ] (config.init or "");
 
-      mkScript = drv: lib.flip map drv.scripts (script: "/script load ${drv}/share/${script}");
+      mkScript = drv: lib.forEach drv.scripts (script: "/script load ${drv}/share/${script}");
 
       scripts = builtins.concatStringsSep ";" (lib.foldl (scripts: drv: scripts ++ mkScript drv)
         [ ] (config.scripts or []));
diff --git a/pkgs/applications/networking/remote/citrix-receiver/default.nix b/pkgs/applications/networking/remote/citrix-receiver/default.nix
index 1f70cb56b54..bf5f5df934d 100644
--- a/pkgs/applications/networking/remote/citrix-receiver/default.nix
+++ b/pkgs/applications/networking/remote/citrix-receiver/default.nix
@@ -58,7 +58,7 @@ let
       versions = [ "13.8.0" "13.9.0" "13.9.1" ];
     in
       lib.listToAttrs
-        (lib.flip map versions
+        (lib.forEach versions
           (v: lib.nameValuePair v (throw "Unsupported citrix_receiver version: ${v}")));
   in
     deprecatedVersions // supportedVersions;
diff --git a/pkgs/applications/networking/remote/citrix-workspace/default.nix b/pkgs/applications/networking/remote/citrix-workspace/default.nix
index 745ad7a9c5d..cf89666a379 100644
--- a/pkgs/applications/networking/remote/citrix-workspace/default.nix
+++ b/pkgs/applications/networking/remote/citrix-workspace/default.nix
@@ -62,7 +62,7 @@ let
       versions = [ ];
     in
       lib.listToAttrs
-        (lib.flip map versions
+        (lib.forEach versions
           (v: lib.nameValuePair v (throw "Unsupported citrix_workspace version: ${v}")));
   in
     deprecatedVersions // supportedVersions;
diff --git a/pkgs/tools/inputmethods/ibus-engines/ibus-typing-booster/wrapper.nix b/pkgs/tools/inputmethods/ibus-engines/ibus-typing-booster/wrapper.nix
index 1115e4e232f..56ddf93af45 100644
--- a/pkgs/tools/inputmethods/ibus-engines/ibus-typing-booster/wrapper.nix
+++ b/pkgs/tools/inputmethods/ibus-engines/ibus-typing-booster/wrapper.nix
@@ -4,7 +4,7 @@
 
 let
 
-  hunspellDirs = with lib; makeSearchPath ":" (flatten (flip map langs (lang: [
+  hunspellDirs = with lib; makeSearchPath ":" (flatten (forEach langs (lang: [
     "${hunspellDicts.${lang}}/share/hunspell"
     "${hunspellDicts.${lang}}/share/myspell"
     "${hunspellDicts.${lang}}/share/myspell/dicts"