Discuss Cursed Nix Koans

Companion thread to Cursed Nix Koans.

Why does redefining __mul work but not __add?

:smiley: Spoilers: #nixos on 2019-11-04 — irc logs

I’m not sure why dealing with strings matters. You should be able to write something like

__add = x: y: if builtins.isString x then
    # do something string-y
  else
    # do something numeric
  ;

Or I guess the other question is why have __add at all since it’s apparently not used.

I’m guessing it’s something about how the parser works and not the evaluation semantics. (If that makes any sense?)

This operator seems to be defined different from the other ones
http://github.com/NixOS/nix/blob/06f9364e5ff3f32e23a82cc9aa166fb47fa9d43c/src/libexpr/parser.y#L355
(sidenote: What’s a CONCAT?)

So after a little digging I found https://github.com/NixOS/nix/blob/e012384fe99bd7d229fffa78f890d3ede915709b/src/libexpr/eval.cc#L1377

So…the semantics of + are hardcoded in the parser? Does __add even get used?
I’m just collecting this stuff :sweat_smile:

Ok maybe me messing around with spoiler tags is kind of pointless :sweat_smile:

Oh no, is this planned for removal? :smiley: nix allows operator overloading of < · Issue #861 · NixOS/nix · GitHub
Huh. Trying to figure this stuff out is pretty educational.

Yeah I dug around in the parser already and found that. I’m amused that + by default goes through something called “string concat”, which itself checks if the first arg is numeric instead. But this is why I asked why we have __add at all since AFAICT it’s never called anywhere.

In any case, operator overloading is cute but I wish it worked like __functor, i.e. that you could define __mul in a set and it would be invoked if that set were used as the LHS of the operator.

I was hoping to do a variant on this that used > instead by defining __lessThan but it turns out that no matter how you define __lessThan, an expression of the form a > b > c is a syntax error. I’m rather curious why this is so; obviously with the default implementation it would be a type error (true > x shouldn’t ever work) but I don’t see a reason for it to be syntactically prohibited.