Open valodzka opened 8 months ago
How does nix implement pseudorandom number generators?
From what I found used approach is to generate sequence.
but are you sure there is no way to implement
Interpolation - Multiple Calls
?
I'm not nix expert so I asked for help, may be someone more knowledgeable than me know the solution.
@jgonggrijp Based on the response to my post on the Nix Discourse forum and also on this similar question
would require something akin to a monadic context But that’s not a thing.
It seems that implementing something similar to a monadic context would be necessary. However, such a concept doesn't currently exist in Nix.
@valodzka Thanks for sharing those links. The next reply to that similar question (comment by AndersonTorres) lists several links with instructions on how you can implement monads yourself. I visited the first one, which illustrated the concept for Scheme. Looking at the Scheme code, I see nothing that is specific to Scheme or that requires variable modifications or other special facilities. I think you could also implement them in C or Nix.
Concluding, I still think it should be possible to implement Interpolation - Multiple Calls
in Nix. Please let me know whether you want to have a go at it, otherwise I will just merge it as-is.
By the way, Wikipedia also has code examples:
https://en.wikipedia.org/wiki/Monad_(functional_programming)
@jgonggrijp after more discussion it looks like it can be implemented but only with a kind of breaking interface. It would require that:
result
for rendering, not returned value itself and pass returned value to parameter to lamda call)So lamda will look like this:
s:
let
state = if s == null then { result = 0; nextState = 1; } else s;
in
{ result = state.nextState; newState = state.nextState + 1; }
I am not sure if this is worth it, but if you think it's necessary I can update the pull request.
@valodzka That comment by rhendric is gold, please pass them my appreciation.
You are right that any stateful lambda will necessarily require interface changes in your Mustache implementation, if your implementation is to pass that test. It is entirely up to you whether you want to invest that effort.
That being said, you can write some monadic form of the lambda for this test, without making any changes anywhere else. This will not break the spec itself, and the only consequence for your implementation is that it will fail this particular test. Which is exactly as it should be; the spec expects implementations to support stateful lambdas, and yours does not (at least not yet).
In other words, please write a monadic form, but do not feel obliged to pass it. I recommend a lambda form that assumes a more generic state monad, so that you can easily add support for other types of stateful behavior later. Something like this:
v: state @ { count ? 1 }:
let
next = count + 1;
in
{ result = count; state = state // { count = next } };
If you later decide to actually support stateful lambdas, the part of your implementation that interpolates them can detect whether a lambda returned a bare value or a monad, and wrap it in a monad with unit
/return
in the first case. In this way, you and your users won't need to rewrite stateless lambdas. The corresponding unit
/return
and bind
/>>=
implementations would look something like this:
unit = value: state: { result = value; state = state };
bind = previous: func: state:
let
intermediate = previous state;
in
func intermediate.result intermediate.state;
I didn't understand you wanted to do Mustache stuff in Nix.
Here's a lead on how to perform "monadic-style" stuff in Nix, though I highly don't recommend relying on this, this is not supposed to be public interface and may be removed in a future version of Nix:
let next = rec { state = 0; __functor = old: _: old // { state = old.state + 1; }; }; in next {} {} {} {} {}
__functor
enable an attribute set to act as a function.
@RaitoBezarius Thanks for chiming in. Assuming that __functor
disappears, would you recommend something more like what I suggested, or would you still recommend a different approach?
Implementent lambdas for nix.
Interpolation - Multiple Calls
skipped because nix is pure functional language so lambda cannot have state / return different result.