[Nix-dev] Re: NixOS: New scheme

Ludovic Courtès ludo at gnu.org
Wed Nov 19 00:40:04 CET 2008


"Nicolas Pierron"
<nicolas.b.pierron at gmail.com> writes:

> Yes. Here is the current implementation analogy:
>
> config_t system(set<pkgs_t> pkgs, ...) {
>   ..;
>   // unmaintainable function call & function arguments
>   upstart_jobs(pkgs.foo, pkgs.bar, pkgs.baz, pkgs.qux, ...); // for
> all packages used below
>   ..;
> }
>
> list<jobs> upstart_jobs(pkgs_t foo, pkgs_t bar, pkgs_t baz, pkgs_t qux, ...) {
>   job1(foo, bar);
>   job42(foo, baz);
>   job51(bar, qux);
> }

It's admittedly not very elegant, but I wouldn't call it
"unmaintainable" since all calls to functions that build Upstart jobs
are independent and can be hacked independently.

FWIW, I did not find it too difficult to dive into that code, but I did
find it inconvenient to have to go touch that many files just to add a
single job.

> So I don't think that this solution can easily be maintain as there is
> lot of code to explain to handle it correctly.  Sure, if you succeed
> to implement something with it, it would probably be more secure.  On
> the other hand you will develop less feature due to this extra
> complexity.

I think this is an exaggeration.  Speaking of how many features are
to be developed, are you planning to port all existing Upstart jobs to
the "new scheme"?

BTW, my post did not mention "security".

> What I am suggesting with this writing is to have independent jobs
> with an identical syntax (less complexity).  So every function will
> become something like:
>
> lazy<config_t> &do_something_well_defined(set<pkgs_t> pkgs,
> lazy<config_t> &config) {
>   // use packages related to the well defined operation.
> }

As I tried to illustrate in my message, the `pkgs' and `config'
arguments here are essentially eye candy; the point is that they allow
to the whole system state to be reached transitively.

> Of course the pkgs and config attributes are some kind of catch all
> set of attributes, but you will only use things related to your well
> defined operation.  Moreover, as it is easier to read it is also
> easier to review and fix.

I don't think it's "easy to review and fix", because it just makes it
impossible to determine which packages Upstart jobs depend on, when
looking at the call sites.

>> A practical consequence is that it makes it very hard to read the code
>> and understand what a function does since it takes input data
>> implicitly, from "the environment".
>
> That is the reason why functions have names.

That's untrue (Upstart job functions are anonymous), and that would be
no substitute.

>>  It also makes it impossible to
>> "virtualize" functions: the second version of `do_things ()' will always
>> use the global `pkgs.foo' and cannot be told to use something else as
>> `foo'.
>
> What do you mean by "virtualize" ?  You mean higher order function ?

I simply mean "changing the data operated on".  E.g., in Nixpkgs, we can
write:

  foobar = import .../foobar {
    inherit foo bar;
    baz = baz23;
  };

  foobarOld = import ../foobar {
    foo = fooOld;
    bar = barOld;
    baz = bazOld;
  };

Such things are much harder to do when the actual parameters are hidden
in a large attribute set like `pkgs'.

>>  In the context of the Nix interpreter, it probably prevents
>> optimizations since it's as if every Upstart job depended on *all*
>> packages (perhaps Eelco can comment on this).
>
> If you prefer you can write something like:
> {pkgs@{lib@{mkOption, ...}, foo, ...}, config, ...}:

Well, just because I prefer something doesn't mean I'll implement it in
NixOS, regardless of what others prefer.  There's a single "NixOS"
project so I find it better to reach a consensus.  ;-)

Thanks,
Ludo'.




More information about the nix-dev mailing list