# Record MVP
###### tags: `Juvix` `juvix-project` `records`
$$
\newcommand\Let{\mathbf{let}\:}
\newcommand\In{\:\mathbf{in}\:}
\newcommand\Return{\:\mathbf{return}\:}
\newcommand\RV[1]{\langle #1 \rangle}
\newcommand\Lett{\mathbf{let}\text-\RV{}}
$$
## Names
Implementing the [current design] of records still has some unanswered questions about the bound names $\bar y$ in $\Let \RV{\bar y} = e \dotsb$:
[current design]: https://hackmd.io/Xlvu82eFQ_m-cebUWAtGsw?view
- they are bound variables, so they must be added to the local context in dependency order
- in the current spec, they can be given in any order
- the name resolution step happens before type checking, so the information to reorder them is not yet available.
It might be possible to get around this by using `PatternVar` instead, but I understand that is on the way out at some point so adding more uses of it is probably not the right way to go.
With all this in mind, I think in the initial implementation we simply require (when checking the $\Lett$ expression) that the names $\bar y$ be in the same order as in the type of $e$. Allowing them to be permuted can be added in future.
With the names in the `let` corresponding exactly to those in the type of `e`, the constructor can be
```
RecElim [Symbol] -- names bound
(Elim primTy primVal) -- record to deconstruct
(Term primTy primVal) -- return type
(Term primTy primVal) -- body
```
and the representation in core of $\Let \RV{\bar y} = e \Return x.A \In s$ can be `RecElim 𝑦̄ 𝑒 𝐴 𝑠`. One variable ($x$, corresponding to the record) is bound in `𝐴`, and one in `𝑠` for each field, with the rightmost field being index `0`.
## Field lookups
Since the $\Lett$ form is (I think) also going to be added to the frontend language, it could be possible to have that be the *only* way to eliminate a record in the MVP implementation, leaving lookup expressions and the passes required to later iterations.
## Do records have $η$?
Not yet, no, because the evaluator isn't type aware. When it is, then since these records are non-recursive, I don't see why they shouldn't.
## Renaming?
Sure. Not in the MVP, probably, but soon after.
Something like
`let {val = x} = e return ... in x`
desugaring to
`let {val} = e return ... in (let x = val in x)`.
## Does this design actually work?
I never gave an example before, so here's a couple
```
sig pair : (a : ty) -> (b : a -> ty) -> ty
let pair a b = {1 fst : a; 1 snd : b fst}
-- ω because the snd field is being dropped
sig fst : pair a b -(ω)-> a
let fst #a p = let {fst; snd} = p return _ => a in fst
sig snd : (p : pair a b) -(ω)-> b (fst p)
let fst #b p =
let {fst; snd} = p
return x => (let {fst; snd} = x return ty in b fst)
in snd
sig two : ty -> ty
let two a = {2 val : a}
sig app : (a -> a -> b) -> two a -> b
let app #b f p =
let {val} = p return _ => b in f val val
```
The body of `snd` looks a bit weird with the nested let, but that's because this is currently the unsugared core form. It would be possible to automatically have the fields be in scope in the `return` clause by adding a desugar step that inserts this extra `let`.
## Is the $x$ in $\Return x. A$ really needed?
I think so? But if not I'll be more than happy to remove it.