Closed sdboyer closed 1 year ago
i'm gonna merge these, with this note...
Recent discussions have absolutely led me to change my mind about the necessity of having Go lenses as an essential part of Thema. They just make all of what Thema is doing considerably easier to at least get started with, because it allows writing the more complex part (lenses) in a familiar language. All the checkable invariants in the world don't matter if the learning curve is too steep.
I'm not sure that what's in this PR is the final form that imperative lenses should take. It does seem to me like there's a plausible path where we actually handle lacuna resolvers as injected funcs, and that the implementation here could be wholly replaced by that. But this PR does the absolute minimal thing necessary to enable lenses in Go, which gets us started. And because it requires a clean split - either there are imperative lenses or declarative ones, no mixing and matching - we have the simplest foundation for changing it later and minimizing impact on users.
This introduces an alternate mechanism for writing lenses: passing in a slice of
ImperativeLens
toBindLineage
:where each function has exactly the same scope of responsibility as would otherwise be fulfilled by a declarative lens written in CUE.
The caller provides these via a new
BindOption
calledImperativeLenses()
. In the current implementation, the caller must choose to implement their lenses entirely in Go, or entirely in CUE. We could relax this later.This isn't fully ready - definitely needs more tests, and the requisite changes to
Translate()
aren't yet implemented. (Though i think those will be like another 40 LoC...trivial). But the test that exists so far at least verifies the correctness of the checker which ensures all and only the exact set of Go migrations are being provided.The test also shows what actually writing Go lenses might plausibly look like - though PLEASE NOTE that when this is put to use in kindsys, we'll be putting in a wrapping layer so that the developer doesn't need to interact directly with
*thema.Instance
.