Skip to content

Commit 5725deb

Browse files
committed
aog wip
1 parent df89971 commit 5725deb

1 file changed

Lines changed: 33 additions & 20 deletions

File tree

src/data_visualization/aog_in_clojure_part1.clj

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,32 @@
338338
;; inspectable. How do we get the compositional approach of AoG while keeping everything
339339
;; as simple Clojure data?
340340

341+
;; ## 📖 The Algebraic Foundation in Clojure
342+
;;
343+
;; Remarkably, Clojure's standard `merge` and `concat` already exhibit distributive-like
344+
;; properties similar to Julia's `*` and `+`:
345+
346+
;; **Merge distributes over concat:**
347+
(let [shared {:data :penguins}
348+
layers [{:plottype :scatter} {:plottype :line}]]
349+
(map #(merge shared %) layers))
350+
351+
;; This mirrors the algebraic property from AoG:
352+
;; ```julia
353+
;; data(penguins) * (scatter + line)
354+
;; = (data(penguins) * scatter) + (data(penguins) * line)
355+
;; ```
356+
357+
;; **Concat preserves structure:**
358+
(concat [{:x :a}] [{:y :b}])
359+
360+
;; **Merge combines properties:**
361+
(merge {:x :a} {:y :b})
362+
363+
;; So we can build `=*` (merge-based) and `=+` (concat-based) that preserve
364+
;; these algebraic properties while working with plain Clojure data. The algebra
365+
;; isn't imposed artificially—it emerges naturally from Clojure's data operations.
366+
341367
;; # Design Overview
342368
;;
343369
;; Before diving into implementation, let's establish what we're building and how it works.
@@ -793,7 +819,7 @@
793819
;; ## ⚙️ Malli Registry Setup
794820
;;
795821
;; Create a registry that includes both default schemas and malli.util schemas.
796-
;; This enables declarative schema utilities like :merge, :union, :select-keys.
822+
;; This enables declarative schema utilities like `:merge`, `:union`, `:select-keys`.
797823

798824
(def registry
799825
"Malli registry with default schemas and util schemas (for :merge, etc.)"
@@ -1172,12 +1198,6 @@
11721198
(throw (ex-info "Layer validation failed"
11731199
errors))))
11741200

1175-
;; **Why this works**:
1176-
;;
1177-
;; - Standard `merge` composes correctly (flat structure)
1178-
;; - No collision with data columns (`:=plottype` ≠ `:plottype`)
1179-
;; - All standard library operations work: `assoc`, `update`, `mapv`, `filter`, `into`
1180-
11811201
;; # API Implementation
11821202
;;
11831203
;; This section implements the core API: the composition operators (`=*`, `=+`),
@@ -2982,12 +3002,12 @@ iris
29823002
;; 1. Each function detects whether its first argument is a plot spec
29833003
;; or data (dataset, map-of-vectors, vector-of-maps)
29843004
;; 2. If data: converts to a plot spec first via `(data ...)`
2985-
;; 3. If a plot spec: merges the new specification using `*`
3005+
;; 3. If a plot spec: merges the new specification using `=*`
29863006
;; 4. Everything returns plot specs, so threading works naturally
29873007
;;
29883008
;; **Both styles work**:
29893009
;;
2990-
;; You can use compositional style with `*`:
3010+
;; You can use compositional style with `=*`:
29913011
;; ```clojure
29923012
;; (=* (data penguins) (mapping :x :y) (scatter))
29933013
;; ```
@@ -3795,13 +3815,6 @@ iris
37953815
;; 3. Points are colored by sex, but regressions computed per species
37963816
;; 4. This shows that grouping and color are independent concepts
37973817

3798-
;; ## 🧪 Example 8: Using `plot` for Spec Inspection and Customization
3799-
3800-
;; Most of the time, layers auto-display and you don't need `plot`.
3801-
;; But sometimes you want the raw target spec for debugging or customization.
3802-
;; See the Multi-Target Rendering section for examples of using `plot`
3803-
;; with `:vl` and `:plotly` targets.
3804-
38053818
;; # Faceting
38063819
;;
38073820
;; Small multiples: splitting data across rows and columns for comparison.
@@ -3903,8 +3916,8 @@ iris
39033916
;; 3. Compute domains across all facets (for shared scales)
39043917
;; 4. Render each facet as mini-plot
39053918
;;
3906-
;; For :geom target - compute layout positions manually
3907-
;; For :vl/:plotly targets - could use their grid layout features
3919+
;; For `:geom` target - compute layout positions manually
3920+
;; For `:vl`/`:plotly` targets - could use their grid layout features
39083921

39093922
;; ## 🧪 Examples
39103923

@@ -4093,7 +4106,7 @@ iris
40934106

40944107
;; 1. Y-axis forced to extend from 0 to 40 instead of auto-computed range from 10.4 to 33.9
40954108
;; 2. Useful for starting axes at meaningful values (like 0)
4096-
;; 3. Custom domains compose via `*` operator
4109+
;; 3. Custom domains compose via `=*` operator
40974110

40984111
;; Custom domains on both axes
40994112
(plot
@@ -5455,7 +5468,7 @@ iris
54555468
;;
54565469
;; **Core Design**:
54575470
;; - Layers as flat maps with `:=...` distinctive keys (see [Design Exploration](#design-exploration))
5458-
;; - Composition using `*` (merge) and `+` (overlay)
5471+
;; - Composition using `=*` (merge) and `=+` (overlay)
54595472
;; - Standard library operations work natively
54605473
;; - Backend-agnostic IR
54615474
;;

0 commit comments

Comments
 (0)