query
On this page

makeScope

lib.customisation.makeScope

Docs pulled from | This Revision | 10 minutes ago


Make an attribute set (a "scope") from functions that take arguments from that same attribute set. See for how to use it.

Inputs

  1. newScope (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a)

    A function that takes an attribute set attrs and returns what ends up as callPackage in the output.

    Typical values are callPackageWith or the output attribute newScope.

  2. f (AttrSet -> AttrSet)

    A function that takes an attribute set as returned by makeScope newScope f (a "scope") and returns any attribute set.

    This function is used to compute the fixpoint of the resulting scope using callPackage. Its argument is the lazily evaluated reference to the value of that fixpoint, and is typically called self or final.

    See for how to use it. See for details on fixpoint computation.

Output

makeScope returns an attribute set of a form called scope, which also contains the final attributes produced by f:

scope :: {
  callPackage :: ((AttrSet -> a) | Path) -> AttrSet -> a
  newScope = AttrSet -> scope
  overrideScope = (scope -> scope -> AttrSet) -> scope
  packages :: AttrSet -> AttrSet
}
  • callPackage (((AttrSet -> a) | Path) -> AttrSet -> a)

    A function that

    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,
    2. Takes an attribute set args with explicit attributes to pass to p,
    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.

    All such functions p will be called with the same value for attrs.

    See for how to use it.

  • newScope (AttrSet -> scope)

    Takes an attribute set attrs and returns a scope that extends the original scope.

  • overrideScope ((scope -> scope -> AttrSet) -> scope)

    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. See for details.

    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.

  • packages (AttrSet -> AttrSet)

    The value of the argument f to makeScope.

  • final attributes

    The final values returned by f.

Examples

Create an interdependent package set on top of pkgs

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.

let
  pkgs = import <nixpkgs> { };
in
pkgs.lib.makeScope pkgs.newScope (self: {
  foo = self.callPackage ./foo.nix { };
  bar = self.callPackage ./bar.nix { };
})

evaluates to

{
  callPackage = «lambda»;
  newScope = «lambda»;
  overrideScope = «lambda»;
  packages = «lambda»;
  foo = «derivation»;
  bar = «derivation»;
}

Using callPackage from a scope

let
  pkgs = import <nixpkgs> { };
  inherit (pkgs) lib;
  scope = lib.makeScope lib.callPackageWith (self: { a = 1; b = 2; });
  three = scope.callPackage ({ a, b }: a + b) { };
  four = scope.callPackage ({ a, b }: a + b) { a = 2; };
in
[ three four ]

evaluates to

[ 3 4 ]

Type

makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> scope

Noogle detected

Aliases

Implementation

The following is the current implementation of this function.

makeScope =
    newScope: f:
    let
      self = f self // {
        newScope = scope: newScope (self // scope);
        callPackage = self.newScope { };
        overrideScope = g: makeScope newScope (extends g f);
        packages = f;
      };
    in
    self;