[Nix-dev] Re: NixOS: New scheme - small explanation of fix

Marc Weber marco-oweber at gmx.de
Wed Nov 19 23:58:20 CET 2008


> Sorry, I don't understand the meaning of "the fix style" either.

Maybe you know about the 

rec {
  a = 7;
  b = a;
};

Using rec you can't pass the whole rec as build input unless you start
duplicating all names

rec {
  a = 7
  b = func { inherit a; inherit b; }; # ugly, redundant..
};

So the next thing to do is (same as first all-packages.nix example which
has been used in the past see [1] below)

let attrs = {
  a = 7;
  b = func attrs ; # eg func = (a : a.a);
}; in attrs

now fix is an abstraction over the last style:

fix ( attrs : {
    a = 7;
    b = func attrs
});

If you think about fix in the use case "global system configuration"
this means that you can read the subversion daemon configuration
settings while configuring the svn module for apache.

I'm using fix in my new python proposal. It looks like this:

p: # pkgs, no longer using with to clarify which derivation is
actually used
let 
  inherit (p) lib fetchurl stdenv getConfig; # for convinience
in
  lib.fix ( t : { # fix is only used for implementing the "all" feature in the wrapper

    pythonWrapper = stdenv.mkDerivation {
      name = "${t.pythonFull.name}-wrapper";
      # [1] using full because installing dozens of different 
      # versions with different support flags isn't any better
      # At least you want readline support
      phases = "buildPhase";
      buildInputs = [ p.makeWrapper ] 
        ++ lib.concatMap (x: if x == "all" then t.all else [x])
          (getConfig ["python26" "wrapperLibs"] []);
      [..]


    all = lib.filter (x: 
                     (__isAttrs x)
                  && ((lib.maybeAttr "libPython" false x) == t.version)
                  && (lib.maybeAttr "name" false x != false) # don't collect pythonLibStub etc
          ) (lib.flattenAttrs (removeAttrs t ["all"])); # nix is not yet lazy enough, so I've to remove all first
})

this way you exactly now where a dependency comes from. It's either
prefixed by t. (this ..) or p. (pkgs)

Anyway we can't call the new scheme the "fix" scheme because fix is
already used in the current scheme :-)

I hope I've shed some light into fix usage for everyone who was scared
when seeing the name until now (?)

fix is used in haskell quite often. That often that it even has
syntactic sugar called mdo.

Sincerly
Marc Weber

[1]

let pkgs = {
# The package compositions.  Yes, this isn't properly indented.
pkg1 = ..
pkg2 = (import ..) { bar = pkgs.bar; };

}

which looks like this nowadays: (much more complicated :-)

  __overrides = (getConfig ["packageOverrides"] (pkgs: {})) pkgsOrig;

  pkgsOrig = pkgsFun {}; # the un-overriden packages, passed to packageOverrides
  pkgsOverriden = pkgsFun __overrides; # the overriden, final packages
  pkgs = pkgsOverriden;


  # The package compositions.  Yes, this isn't properly indented.
  pkgsFun = __overrides: rec {




More information about the nix-dev mailing list