The generated code is safe, but the `reset/reuse` optimization will
never be applicable at runtime. The issue is that
`insert_reset_reuse_fn` is not checking the joint points.
I will fix the bug only at `resetreuse.lean`.
@kha Trying again :)
I started using the prefix `f` for the `Fin` version (e.g., `fswap` and
`fswapAt`). So, it seemed natural to use the prefix `f` for the `Fin`
versions of `get` and `set`.
BTW, is it too crazy to use `a[i]` (without spaces) as notation for
`a.get i`? The constraint is to make sure `f a [i]` is not ambiguous.
That is, `f a[i]` is `f (a.get i)` and `f a [i]` is `f a (i::nil)`.
This is doable with the new parser.
Then, we could have `a[i]` as notation for `a.fget i` if `i` is a `Fin`,
and `a.get i` if `i` is `Nat`.
Similarly, `a[i := v]` would be notation for `a.fset i v` if `i` is
`Fin`, and `a.set i` if `i` is `Nat`.
It would also be awesome to have
```
let a[i] := v in
e
```
as notation for
```
let a := a[i := v] in
```
@kha I created a variant of the `rbmap` example where we create a tree
but also save "checkpoints". The idea is to simulate the idiom frequently
used in a backtracking search where we "save" the "context" before each
case split in a "trail stack".
The benchmark has two parameters: the number of nodes to be inserted, and a "frequency" (how often we create a "checkpoint").
The command `rbmap_checkpoint.lean.out n n` behaves like the original
`rbmap` benchmark, and `rbmap_checkpoint.lean.out n 1` creates a
checkpoint after each insertion. The frequency provides a simple way to
control the amount of sharing. We can provide performance numbers for
different frequencies, and show the impact on the `reset/reuse` optimization.
BTW, the performance numbers are much better than I expected. For
example,
`./rbmap_checkpoint.lean.out 1000000 10` is only 30% slower than
`./rbmap_checkpoint.lean.out 1000000 1000000`
although 100k checkpoints were created.
Another good news is that we are faster than Haskell even for
`./rbmap_checkpoint.lean.out 1000000 1`