Description
Describe the bug
Some functions, such as those for getting an attribute value are strict.
This is unexpected in a lazy language, and for the bindings to diverge from the language semantics is a recipe for subtle mistakes that make applications behave worse, probably unknowingly.
Example: forward an attribute in a primop implementation
- write a primop that expects an argument like
{ meta, ... }:
, and returns something likex // { inherit meta; }
- get the argument
- make sure it's an attrset
- store the
meta
Value
in a local variable - do whatever the primop is supposed to do
- return an attrset which includes
meta
- observe that this code breaks
There's no reason for this not to work! The only reason why this fails is that
let x = myprimop { inherit meta; foo = "bar"; } meta = x.foo.meta // { bar = true; }; in x
nix_get_attr_byname
forces the value.
I know that the team has argued for making the C API simpler by avoiding thunks, but I now believe this is contradictory.
By "avoiding thunks", we create an API that is less capable and will have to eventually be extended to included mirrored functions that do the exact same thing, except the redundant .force
call.
Simplicity in a library is achieved by orthogonalizing its features, not by spreading responsibilities across the whole interface.
Also note that we are currently trading an obvious error with a simple and obvious solution for a subtle error that requires a thorough understanding of Nix laziness to understand that it can even be solved. Let's not do that.
Steps To Reproduce
See above for example.
Expected behavior
The C API is no more eager than the language itself.
nix-env --version
output
Additional context
Priorities
Add 👍 to issues you find important.