Skip to content

Conversation

@llakala
Copy link
Contributor

@llakala llakala commented Nov 30, 2025

WIP, but this is working in the tests I've done. Closes #15.

@llakala llakala force-pushed the try-adding-input-impls branch 30 times, most recently from 734c375 to 218cecf Compare November 30, 2025 22:36
@llakala llakala force-pushed the try-adding-input-impls branch 2 times, most recently from 0585659 to f998bb8 Compare December 1, 2025 05:02
@llakala llakala marked this pull request as ready for review December 1, 2025 05:40
@llakala
Copy link
Contributor Author

llakala commented Dec 1, 2025

This is now good for review - I'm using this PR here to great results. Here's a demo of how you can call another module's impl (in this case, less):

  impl =
    { options, inputs }:
    let
      inherit (inputs.nixpkgs) pkgs lib;
      inherit (pkgs) symlinkJoin makeWrapper;
      lessWrapper = inputs.less {};
    in
    symlinkJoin {
      name = "bat-wrapped";
      paths = [ pkgs.bat ];
      buildInputs = [ makeWrapper ];
      postBuild = /* bash */ ''
        wrapProgram $out/bin/bat \
          --add-flags "${options.flags}" \
          --add-flags "--pager='${lib.getExe lessWrapper} -RFX'"
      '';
      meta.mainProgram = "bat";
    };

We also add the ability for you to call the current module's impl within a defaultFunc, to allow stuff like this:

  options.iniConfig = {
    type = types.attrs;
    defaultFunc =
      { options, inputs }:
      let
        inherit (inputs.nixpkgs) lib;
        finalWrapper = options {};
      in {
        credential."https://github.com".helper = "${lib.getExe finalWrapper} auth git-credential";
      };
  };

I don't love the semantics of options {} to call the current module's impl - but I think it's the best we can do for now. In the future, if we decided on revamping our API to use { inputs, self }, and require doing self.options.foo to read from options, this could be improved.

Finally, you can create cool kinds of nested data structures with this, since an impl can now call itself:

{ adios }:
{
  options = {
    foo = {
      type = adios.types.int;
      default = 0;
    };
  };

  impl = { options }: {
    foo = options.foo;
    bar = options { foo = options.foo + 1; };
  };
}

If we inspect the result of this in the repl, we can see what this does:

nix-repl> wrappers.temp {}          
{
  bar = { ... };
  foo = 0;
}
nix-repl> (wrappers.temp {}).bar
{
  bar = { ... };
  foo = 1;
}
nix-repl> (wrappers.temp {}).bar.bar
{
  bar = { ... };
  foo = 2;
}

Enjoy your arbitrarily nested successor function!

There's also space to improve memoisation here in the future, since two modules doing inputs.foo {} will recompute the same function call. Always more to do!

By doing `inputs.foo {}` within an `impl` or `defaultFunc`, `foo`'s impl
will be called.
By doing `options {}`, you can now call the current impl.
@llakala llakala force-pushed the try-adding-input-impls branch from f998bb8 to 1d39950 Compare December 1, 2025 17:07
@poach3r
Copy link

poach3r commented Dec 5, 2025

+1 im using this personally and havent found any issues

@llakala
Copy link
Contributor Author

llakala commented Dec 5, 2025

Poacher said, before finding an issue...
(Looking into it)

@llakala llakala force-pushed the try-adding-input-impls branch 4 times, most recently from 2db5958 to 027625d Compare December 6, 2025 15:27
Silly bug. When we call a module's functor with some args, we can't get
away with just calling the `impl` of the module. Before, we only
performed a merge with the old args and new args within the functor for
some input module - so you could do `inputs.foo {}`. But a merge isn't
good enough. We have to recompute any/all `defaultFunc`s that the module
might have.
@llakala llakala force-pushed the try-adding-input-impls branch from 9b25e7c to 48820f1 Compare December 6, 2025 15:35
@llakala
Copy link
Contributor Author

llakala commented Dec 6, 2025

Bug fixed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide access to another module's impl

2 participants