NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
12.59k stars 1.51k forks source link

Named ellipses #2998

Open deliciouslytyped opened 5 years ago

deliciouslytyped commented 5 years ago

I don't know what ... is called syntactically and searching ellipses didn't yield any relevant issues.

I think it would be nice if we could name the ... that is the extra parameters to a function, because it would mean we don't have to use builtins.removeAttrs to clean things up when one wants to just do {...}: { ..whatever.. } // extra. So this would clean up a lot of code?

Perhaps something like the following but maybe better syntax?: {a, b, c, ...@extra}@args: { ..whatever.. } // extra.

(How do other languages handle this?)

infinisil commented 5 years ago

I think the { a, ...@extra }: / { a, extra@... }: would be a nice and simple syntax extension that makes sense (everything in a function argument can bound with @ like this) and makes code nicer.

deliciouslytyped commented 5 years ago

So I guess if I wanted to try implementing this, I would need to: (mostly found via searching for "formals" and "ellipses")

deliciouslytyped commented 5 years ago

I've never done anything like this before, how can I try to implement it?:

The syntax changes look relatively simple. For evaluation I would need to add a formal argument, and also construct some sort of scope object for the formal argument? This would need to be constructed at eval time and the contents should show up in two places?:

stale[bot] commented 3 years ago

I marked this as stale due to inactivity. → More info

stale[bot] commented 2 years ago

I closed this issue due to inactivity. → More info

Artturin commented 1 year ago

Another issue asking for the same thing https://github.com/NixOS/nix/issues/2507

roberth commented 1 year ago

Generally, I would recommend to split your usage of attrsets into two roles:

When you stick to this dichotomy, the need to removeAttrs almost any attributes evaporates, with the added benefit that a dictionary entry can never collide with a record field. Furthermore the intent of the attributes becomes a bit more clear.

In the hercules-ci github organization, I have a whole bunch of projects, but very few uses of removeAttrs, and none would benefit from this.

For me the most significant use of removeAttrs in my code is in hercules-ci-effects, filtering out arguments that aren't valid for mkDerivation. That's emulating the Nixpkgs "generic mkDerivation" pattern, which is particularly worthy of regret. I'm resolving it in that project by migrating it to the module system instead. The module system enforces the same division, thoroughly by enforcing it through types.attrsOf and types.submodule, but with the notable exception of

That all said, it is actually the module system that may be a reason why I might not oppose this change. Its unifyModuleSyntax function is invoked 10745 times instantiating just nixosTests.simple and its behavior could possibly be simplified a lot, from traversing a non-trivial amount of AST to a single lambda invocation. However, this also requires the pattern match to be lazy!

(The number is in the correct ballpark, considering the 1385 root modules (module-list.nix), submodules, mkRenamedOptionModule, etc)

So, to avoid a false sense of improvement, my recommendation is to refactor the code instead, to get double the benefit, at the interface level, instead of a bit of DRY at the implementation level (so more than double? anyway, who's counting. It's strictly more). If you do wish to implement this, implement lazy matching as well, and only continue it if we can get a speedup in the module system.

It is just a recommendation; I won't oppose this, but it is a serious one.