(u/sci-macro let-coordinates
"similar to a `let` binding that holds pairs of
<coordinate-structure-prototype>, <coordinate-system>
And internally binds, for each pair: (take `[x y]` and `m/R2-rect` as
examples):
- The coordinate system symbol `R2-rect` to a new version of the coordinate
system with its `coordinate-prototype` replaced by the one you supplied.
That's `(up x y)` in this example.
- the entries `x` and `y` to coordinate functions, i.e., functions from manifold
point to this particular coordinate
- `d:dx` and `d:dy` vector field procedures (I'm fuzzy here!)
- `dx` and `dy` 1-forms for each coordinate (fuzzy here too!)
Example:
```clojure
(let-coordinates [[x y] R2-rect
[r theta] R2-polar]
;; bindings:
;; R2-rect, x, y, d:dx, d:dy, dx, dy
;; R2-polar, r, theta, d:dr, d:dtheta, dr, dtheta
body...)
```"
[bindings & body]
(when-not (even? (count bindings))
(u/illegal "let-coordinates requires an even number of bindings"))
(let [pairs (partition 2 bindings)
prototypes (map first pairs)
c-systems (map second pairs)
system-names (map (comp symbol name) c-systems)
coordinate-names (mapcat symbols-from-prototype prototypes)
coordinate-vector-field-names (map vf/coordinate-name->vf-name coordinate-names)
coordinate-form-field-names (map ff/coordinate-name->ff-name coordinate-names)]
`(let [[~@system-names :as c-systems#]
(mapv m/with-coordinate-prototype
~(into [] c-systems)
~(mapv quotify-coordinate-prototype prototypes))
~(into [] coordinate-names)
(flatten
(map coordinate-functions c-systems#))
~(into [] coordinate-vector-field-names)
(flatten
(map vf/coordinate-system->vector-basis c-systems#))
~(into [] coordinate-form-field-names)
(flatten
(map ff/coordinate-system->oneform-basis c-systems#))]
~@body)))