How to pronounce “Nixtamal”?
/nɪʃ.təˈmal/ or /ˈnɪkstəˌmɑːl/
The Nahuatl pronunciation is a bit better, but no qualms with an anglicized pronunciation — as folks are probably used to Nix as /ˈnɪks/.
Additionally, ·𐑯𐑦𐑖𐑑𐑩𐑥𐑭𐑤 is a valid spelling for en-Shaw.
What does the name mean?
: limed kernels of [maize] that is ready to be ground into masa
This loosens the maize’s outer hull, so it grinds easier & feeds you better — making it key to Mesoamerican food & health.
Isn’t Nixpkgs big/overkill to do pinning?
Big, yes.
Overkill… it’s not as simple.
In order to get access to the fetchers, one would need to bootstrap their setup & build their own derivation.
This includes at minimum a C compiler & some form of coreutils… except you need more than this.
For instance if you want to use pkgs.fetchdarcs or even create your own, you need a Darcs binary, which requires the Haskell tooling (or all static binaries built for specific platforms).
When you take a look at how that would be set up, you would effectively be reimplementing Nixpkgs.
As such, the simpler answer is to say Nixpkgs is required.
We can giggle about the size of that dependency, but the reality is 98% of projects using Nix are going to be using Nixpkgs anyhow.
Nixtamal does offer configuration when importing it which can be used to provide a minimal package set if needed.
Wishful thoughts would be if Nixpkgs weren’t so monolithic, so that core features like compilers & fetchers could be separate from general packaging, but where these lines get drawn are not clear or simple.
Why OCaml as the main programming language?
Nix the programming language falls in the ML family & share a lot of syntax & conventions with other functional languages in the family. This makes the code more approachable to those familiar with Nix rather than needing to learn a very different language like Niv (Rust) or Yae (Go). The compile times are fast & the ecosystem is sufficient.
Why KDL for the manifest language?
KDL has a syntax that isn’t a burden to use a configuration language — which helps explain why is very popular for its age.
JSON has no comments, one must watch commas, & is verbose with quotations.
TOML doesn’t nest well.
YAML is overly complex.
Nickel is great, but needs to be transformed into one of these others.
EDN was considered, but KDL felt better to write – especially the fresh-cmd syntax using $ & | as node names.
Why not KDL for the lockfile?
Nix does does not have a builtins.fromKDL (tho there has been some rumblings for formats.kdl in Nixpkgs).
As such your options are builtins.fromJSON or builtins.fromTOML & the Rust community’s obsession with TOML & that TOML needs to integrate JSON syntax anyway (just like YAML), it tips the scales in JSON’s favor.
Why is the project using Darcs & not Git?
Patch Theory is cool where patches commute (order doesn’t matter) which eliminates an entire set of merge conflicts present in snapshot-based VCSs. Pijul has the same theory behind it, is faster, & I like the new identity concept, but still lacks tooling. By using Darcs I can also dog food support for the tool. Git uses an arcane, obtuse CLI commands that everyone knows is overly complicated & inconsistent.
What is wrong with with forge-specific URL schemes or semantics?
Trends shift — what’s beloved now likely won’t be tomorrow. Rather than a minor convenience for what is popular now, a better design is to not give any place special privilege. This special privilege can make folks feel peer pressured into using the current trend platform (especially proprietary code forges for free software). We don’t want to foster this behavior — no, we want to see more self-hosting where a code base is truly owned by its makers, even if just for a backup mirror. This also lessens the maintenance burden as APIs shift & ‘mine too’-ing of someone’s unsupported platform.
What is wrong with Nix flakes?
Well this is a hairy topic that it sure to ruffle feathers… First, we should address that flakes aren’t just version pinning (Nixtamal’s current focus) but an enforced pattern of project layout & composition (or lack thereof depending on how you argue that). So let’s focus on the differences from the context of input pinning for now… Flakes might be builtin but it requires enabling an experimental flag; this might sound innocuous — especially given the prevelance of enabling it in the Nix community but it has some serious downsides.
-
Flakes were originally designed for specific client’s needs which might not match your own
-
Since it’s experimental, it’s not versioned (meaning no
version = "1.0.0";inflake.nix) which ties the implementation to a version of Nix without a reasonable indicator to migrate or rollback to a version which leads can lead to unforeseen or catastrophic issues now that we are relying on the state of Nix on the machine -
Flakes have been largely “stable” in so far as it’s they are now a political topic meaning all proposals have been gridlocked on both bikeshedding & serious topics
-
There have been external efforts to stablize like Deteriminate Nix, Lix, & so forth, but now you are reliant on a specific fork for stability; Like how every claims “just Markdown”, but Markdown being underspecified for the task means each fork (sometimes disguised as “flavor”), these version too will be imcompatble despite sharing
flake.nix+flake.lockfiles -
Being built-in & not a third-party tool or pattern makes it harder to fork it reasonably & also stifles diversity & innovation as other option will be seen as more friction even if offering something simpler since an extra tool is involed
Outside of the experimental nature we have other issue that affect pinning:
-
We are limited to the built-in fetchers/fetch-tree & if you read the bug tracker for
nixthey don’t seem terribly interested in adding more fetcher support since they already have a lot to maintain — including the burden of trying to maintain these shorthands for specific hosts; if you wanted it to support Darcs, Pijul, Fossil, or the next big VCS, tough luck -
The URI scheme is nice until it isn’t where expressing more complexity become a subjectively unreadable-long string of query parameters
-
The URI scheme doesn’t support mirrors
-
Overlays offer better compositionality than
input.*.followsbutfollowsis treated more as the preferred option -
Dependency explosion as all inputs are now added to your lock & fetched (even ones just use for ‘development’, or largely useless ones like
flake-utilswhich hides the complexity of the Flake API in a dangerous way since the whole point was to be explicit about declaring what systems are supported); by providing an overlay you can skip this -
Patching inputs are not intuitive & some really wild options have been propused to try to deal with it
If you want to know about flakes schema criticisms, you can ask other places 🙂
But can I use Nixtamal with flakes?
You are welcome to use Nixtamal inside a flake.nix to get access to the the better experience that new Nix command setting offers (which sadly just work better with flakes instead of being more generic).
It would look a little something like:
{ # No longer any need for inputs # inputs = { }; outputs = { self }: let inputs = import ./nix/tamal { }; pkgs = import input.nixpkgs { system = "x86_64-linux"; config = { }; overlay = [ (import "${inputs.MY-PROJECT}/nix/overlay") ]; }; in { # … }; }
If you want that forAllSystem function, you can build your own with builtins, or the standalone nixpkgs.lib mirror, or add flake-utils — which now has a use case since we don’t have access to Nixpkgs or lib (but don’t blindly use eachDefaultSystem).
If this feel unergonomic, this is tradeoff for using flakes — which has pros & cons against Classic Nix as you must define upfront your supported systems (& you must do it correctly, meaning you don’t declare systems you don’t support or haven’t tested as well as supporting all systems that are actually supported else users that could be supported have their ability to try removed).
Classic Nix, you let the downstream user decide (even unsafely) what system means & only MY-PACKAGE.meta.platform to assert system support.