Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: introduce foreach, combined and combined map idioms #57091

Closed
wants to merge 1 commit into from

Conversation

danbst
Copy link
Contributor

@danbst danbst commented Mar 8, 2019

This PR adds foreach and combined functions. They are repainted
versions of following standard lib functions:

  • foreach == flip map
  • foreach == flip mapAttrs when applied to attrset
  • combined == concatStrings
  • combined "sep" == concatStringsSep "sep"
  • combined map == flip concatMapStrings
  • combined "sep" map == flip (concatMapStringsSep "sep")

The idea behind this rename is to encourage flipped usage of functions
in templaters and other script generators.

Flipped version are often easier to read. They are also more consistent with
existing usage of optional, optionalAttrs, mkIf in sense that
usually first argument is shorter (syntatically) than second.

I rewrote two files in Nixos to show how these new functions should be used.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Assured whether relevant documentation is up to date
  • Fits CONTRIBUTING.md.

This PR adds `foreach` and `combined` functions. They are repainted
versions of following standard lib functions:
- `foreach        == flip map`
- `foreach        == flip mapAttrs` when applied to attrset
- `combined       == concatString`
- `combined "sep" == concatStringSep "sep"`
- `combined map   == flip concatMapStrings`
- `combined "sep" map == flip (concatMapStringsSep "sep")`

The idea behind this rename is to encourage flipped usage of functions
in templaters and other script generators.

Flipped version are often easier to read. They are also more consistent with
existing usage of `optional`, `optionalAttrs`, `mkIf` in sense that
*usually* first argument is shorter (syntatically) than second.
@infinisil
Copy link
Member

I'm okay with the foreach function, its two forms can be explained as "Takes an iteratable data structure and a function that gets executed for each element". But combined feels just like a mess, I have no idea what those 4 forms are supposed to be and I think it would be more confusing than anything.

@danbst
Copy link
Contributor Author

danbst commented Mar 9, 2019

@infinisil I found that most unreadable code is in script generators. And those use concatMapStrings and concatMapStringsSep, and exactly here is where code is 👀 bleeding. An option to solve that problem is to replace usages with flip concatMapStrings and flip (concatMapStringsSep "sep"). I found many places where this was already written.

So yeah, all 4 forms do have separate names, and we can live with that... except that it still looks ugly to me.

Maybe I should change description, to make it more user-friendly:

/* `combined` concatenates collection to a string. If supplied with a separator
   and collection, it uses that separator. `combined map` is an idiom to concatenate
   collection, but apply a function to each element of collection (function is supplied
   in last argument).

      combined map collection (element:
         ...here element is converted to a string...
      )

  `combined "sep" map` is a variant of `combined map`, which uses separator "sep"
  for concatenations.
*/

I can split it into two functions combine (concatenate) and combined map (concat with flipped map). I'm also interested what others think about variadic arguments functions and semantics based on argument type.

@aanderse
Copy link
Member

@danbst Care to push this ahead with just foreach for now and defer decisions on the other functions for later? Or come to a decision on all of the functions now?

@danbst
Copy link
Contributor Author

danbst commented Jul 14, 2019

@aanderse done #64723. I've removed varargs behavior to keep it simple.

Overall, I still love my combined and combined map approach, even if it sounds complicated. So ruby. Maybe also embed #57584 into combined map

And while we are here, the support from Nix for python-styled generators would also be great. NixOS/nix#2543

@danbst
Copy link
Contributor Author

danbst commented Aug 18, 2019

Closing this now, maybe another time.

@danbst danbst closed this Aug 18, 2019
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/would-you-like-to-use-nix-instead-of-consul-template-templating-language/5145/1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants