doc: actually document `lib.customisation.makeScope` (#294194)

* doc: actually document `lib.customisation.makeScope`

authored by Valentin Gagarin and committed by GitHub 41298a0d 32146f31

+122 -11
+122 -11
lib/customisation.nix
··· 306 in if drv == null then null else 307 deepSeq drv' drv'; 308 309 - /* Make a set of packages with a common scope. All packages called 310 - with the provided `callPackage` will be evaluated with the same 311 - arguments. Any package in the set may depend on any other. The 312 - `overrideScope'` function allows subsequent modification of the package 313 - set in a consistent way, i.e. all packages in the set will be 314 - called with the overridden packages. The package sets may be 315 - hierarchical: the packages in the set are called with the scope 316 - provided by `newScope` and the set provides a `newScope` attribute 317 - which can form the parent scope for later package sets. 318 319 - Type: 320 - makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> AttrSet 321 */ 322 makeScope = newScope: f: 323 let self = f self // {
··· 306 in if drv == null then null else 307 deepSeq drv' drv'; 308 309 + /** 310 + Make an attribute set (a "scope") from functions that take arguments from that same attribute set. 311 + See [](#ex-makeScope) for how to use it. 312 + 313 + # Inputs 314 + 315 + 1. `newScope` (`AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a`) 316 + 317 + A function that takes an attribute set `attrs` and returns what ends up as `callPackage` in the output. 318 + 319 + Typical values are `callPackageWith` or the output attribute `newScope`. 320 + 321 + 2. `f` (`AttrSet -> AttrSet`) 322 + 323 + A function that takes an attribute set as returned by `makeScope newScope f` (a "scope") and returns any attribute set. 324 + 325 + This function is used to compute the fixpoint of the resulting scope using `callPackage`. 326 + Its argument is the lazily evaluated reference to the value of that fixpoint, and is typically called `self` or `final`. 327 + 328 + See [](#ex-makeScope) for how to use it. 329 + See [](#sec-functions-library-fixedPoints) for details on fixpoint computation. 330 + 331 + # Output 332 + 333 + `makeScope` returns an attribute set of a form called `scope`, which also contains the final attributes produced by `f`: 334 + 335 + ``` 336 + scope :: { 337 + callPackage :: ((AttrSet -> a) | Path) -> AttrSet -> a 338 + newScope = AttrSet -> scope 339 + overrideScope = (scope -> scope -> AttrSet) -> scope 340 + packages :: AttrSet -> AttrSet 341 + } 342 + ``` 343 + 344 + - `callPackage` (`((AttrSet -> a) | Path) -> AttrSet -> a`) 345 + 346 + A function that 347 + 348 + 1. Takes a function `p`, or a path to a Nix file that contains a function `p`, which takes an attribute set and returns value of arbitrary type `a`, 349 + 2. Takes an attribute set `args` with explicit attributes to pass to `p`, 350 + 3. Calls `f` with attributes from the original attribute set `attrs` passed to `newScope` updated with `args, i.e. `attrs // args`, if they match the attributes in the argument of `p`. 351 + 352 + All such functions `p` will be called with the same value for `attrs`. 353 + 354 + See [](#ex-makeScope-callPackage) for how to use it. 355 + 356 + - `newScope` (`AttrSet -> scope`) 357 + 358 + Takes an attribute set `attrs` and returns a scope that extends the original scope. 359 + 360 + - `overrideScope` (`(scope -> scope -> AttrSet) -> scope`) 361 + 362 + Takes a function `g` of the form `final: prev: { # attributes }` to act as an overlay on `f`, and returns a new scope with values determined by `extends g f`. 363 + See [](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.fixedPoints.extends) for details. 364 + 365 + This allows subsequent modification of the final attribute set in a consistent way, i.e. all functions `p` invoked with `callPackage` will be called with the modified values. 366 + 367 + - `packages` (`AttrSet -> AttrSet`) 368 + 369 + The value of the argument `f` to `makeScope`. 370 + 371 + - final attributes 372 + 373 + The final values returned by `f`. 374 + 375 + # Examples 376 + 377 + :::{#ex-makeScope .example} 378 + # Create an interdependent package set on top of `pkgs` 379 + 380 + The functions in `foo.nix` and `bar.nix` can depend on each other, in the sense that `foo.nix` can contain a function that expects `bar` as an attribute in its argument. 381 + 382 + ```nix 383 + let 384 + pkgs = import <nixpkgs> { }; 385 + in 386 + pkgs.lib.makeScope pkgs.newScope (self: { 387 + foo = self.callPackage ./foo.nix { }; 388 + bar = self.callPackage ./bar.nix { }; 389 + }) 390 + ``` 391 + 392 + evaluates to 393 394 + ```nix 395 + { 396 + callPackage = «lambda»; 397 + newScope = «lambda»; 398 + overrideScope = «lambda»; 399 + packages = «lambda»; 400 + foo = «derivation»; 401 + bar = «derivation»; 402 + } 403 + ``` 404 + ::: 405 + 406 + :::{#ex-makeScope-callPackage .example} 407 + # Using `callPackage` from a scope 408 + 409 + ```nix 410 + let 411 + pkgs = import <nixpkgs> { }; 412 + inherit (pkgs) lib; 413 + scope = lib.makeScope lib.callPackageWith (self: { a = 1; b = 2; }); 414 + three = scope.callPackage ({ a, b }: a + b) { }; 415 + four = scope.callPackage ({ a, b }: a + b) { a = 2; }; 416 + in 417 + [ three four ] 418 + ``` 419 + 420 + evaluates to 421 + 422 + ```nix 423 + [ 3 4 ] 424 + ``` 425 + ::: 426 + 427 + # Type 428 + 429 + ``` 430 + makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> scope 431 + ``` 432 */ 433 makeScope = newScope: f: 434 let self = f self // {