Use `haumea.lib.load` as functor for flake itself
This may be a bit of a controversial feature suggestion, but if we use the nix feature to declare __functor in attrs, we can make attribute sets callable. This way we can make the haumea flake itself callable. Since we have a go-to function that most people would want to be using with haumea.lib.load, we could make that the default function of the flake. If we write in the main flake:
outputs = { self, nixpkgs }: rec {
# ...
__functor = _system: args: self.lib.load args;
};
Then, in a using flake we could write:
outputs = { self, haumea, nixpkgs }: {
lib = haumea {
src = ./src;
inputs = { inherit (nixpkgs) lib; };
};
};
That's interesting! I'll have to think about that
After some discussion, I decided to hold off on this because of the added complexity and that haumea.lib.load is decently short.
I will keep this issue open for now for visibility. I'm still open to suggestions, I might change my mind if more people want to see this.
I like it's shortness and make use of this myself. Every well-scoped library has a prime interface. Haumea's is lib.load.
But I'm qlso not too attavhed to the general flake schema. :smile: That's probably why, to me, it feels like a reduction in verbosity rather than a deviation from the standard.
I am posting in a pretty stale issue here, but I'm actually for using lib.load as a __functor for haumea.
After some discussion, I decided to hold off on this because of the added complexity and that
haumea.lib.loadis decently short.
I don't think that's the correct level of analysis. Indeed, there is a very simple metric of "you save keystrokes" you improve, but I don't think that's a very compelling improvement in haumea's case: like you said, it's a short attr path to the func, and the func's name itself is short. Additionally, it's also probably not going to be called that often in a single project, so you're not saving that many keystrokes in aggregate either.
Rather, I think the compelling case for __functor is its simplicity and orthogonality. It's easier to remember (inputs.haumea.lib.load are four components to remember, inputs.haumea are two) and more importantly, it's orthogonal with regards to the load function. Like @blaggacao mentioned, haumea lends itself well to "prime interface" design. There's no reason that lib.load has to be this entrypoint, set in stone; you're contractually requiring the path lib.load to exist in haumea for all eternity, unless you want hundreds of flakes consuming haumea to simultaneously break after an update. If you're calling haumea.lib.load from a functor on the other hand, there's a lot more flexibility in changing implementation details later down the line.
I think the infamous "__functor complexity" is highly overblown, and people just assume "magic attrset member" -> scary witchcraft (you know what other famously complex language also has this functionality? Python....). Mapping { __functor = _: _: ...; } to "this is a callable attrset" in your brain is a one-time knowledge cost you incur when learning Nix, and takes at most a few minutes to grok. It's fully reasonable to expect that people learn how it works, and I think the gains are worth it in the final analysis.