-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recursive records and recursion #83
Comments
As a slight aside, we should consider getting rid of nested records because they make things unnecessarily complicated. For example, with Nixpkgs overlays, it's easy to override a top-level package So the record Edit: this is more relevant to #84, since it means |
I think my preference would be for something that behaves like the NixOS module system, but without any special syntax like |
Is this closed by #135? Sounds like the decision was made there to not require an explicit |
In Nix, the rec keyword allows a field of a record to cross-reference the other fields of the same record. Jsonnet also provides this possibility via self. This is commonly used for sharing and reusing data as in (Nix syntax):
We propose to add recursive records to Nickel.
General recursion
Recursive records are a source of general recursion (although not the only one), as fields may reference themselves, directly or indirectly. This is exemplified in the definition of
flatten
above. Nickel is a configuration language, and most of its use cases should not require the use of general recursion. Several languages competing in the same domain are not Turing-complete, such as Dhall, CUE or Starlark. But recursion is hard to rule out in an untyped language with higher-order functions:rec
or mutually recursive top-level procedures may introduce direct or indirect recursionThe aforementioned languages sidestep these points because:
Moreover, even if rare, there are legitimate cases which require general recursion. Our intent is to offer great defaults, in particular for building and traversing data structures so that explicit recursion is almost never needed. But also to offer an escape hatch when there is no better solution. We propose to introduce recursion and recursive records, but in a way that makes accessing true recursion really explicit, or even a bit awkward.
Proposals
Recursive records
1. à la Nix
Add a
rec
keyword which, when put before the definition a record, brings all the fields in scope.2. Self/This
Introduce a special variable which refers to the current record,
self
, to access other fields.parent
orsuper
keyword for that, or to allow let bindings inside records to capture self in a local variable (both are done in Jsonet)3. Recursive let-binding
as in OCaml, use an explicit
let rec
form for recursive bindings. A recursive record can be written aslet rec r = {a=0; b=r.a+1}
[1]General recursion
A simple solution to discourage recursion is to only rely on recursive records, without explicit recursive functions. This makes it accessible but awkward enough so that the user knows he is doing something non standard. Even more:
let rec
to records.rec
also at the (recursive) call site (as in Bosque), as in the fictitiouslet rec loop n = if n > 0 then rec loop (n - 1) else "done"
.If on the contrary, one wants to provide a direct syntax for recursive
functions:
Late binding
It may be desirable for inheritance-like mechanisms to late bind
self
(or recursive fields in case 1.). In particular, when merging,self
would be bound to the resulting record:People simulates this capacity in Nix using fixpoints for overriding packages, and Jsonnet's
self
is late bound. This may also prove essential for incremental evaluation.let rec
is restricted in practice.The text was updated successfully, but these errors were encountered: