Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to clarify substitution example paragraph #18

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ _Substitution Keys_ can be considered or thought of in two ways. They are the ke

The second way of thinking about substitution keys is that they are the starting values of keys in templates. So, they represent parameterized values of keys in templates.

As an example consider the following. In a template we have a field and value `:field :X`. The `:X` here is a substitution key - it will be replaced as the value of `:field` during transformation by _its_ value in the current substitution map. In the default substitution map `hc/_defaults` `:X` has a value of "x", so the result will be `:field "x"`.
As an example consider the following. In a template (which is a Clojure map) we might have a key `:field` with value `:X` (cf. [xy-encoding template](https://github.com/jsa-aerial/hanami/blob/0dd9ac62e89ec5a5d0285cd0c0da5e2bc87b2ad0/src/cljc/aerial/hanami/templates.cljc#L84)). Here `:field` corresponds to a Vega-Lite key, ["field"](https://vega.github.io/vega-lite/docs/field.html). When we apply `hc/xform` to the template, `:field`'s value `:X` will be replaced by a new value, which comes from the current substitution map. In the default substitution map [`hc/_defaults`](https://github.com/jsa-aerial/hanami/blob/9cfa38118486fa0e139defeaa20ac3595690c8f9/src/cljc/aerial/hanami/common.cljc#L161), the key `:X` has the value of `"x"`, so the resulting key/value pair will be `:field "x"`.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thanks for thinking about this. Some of what you write I believe would communicate the intent better. I think the links here may just distract and the parenthetical note is either redundant or actually a bit misleading (the first argument to hc/xform can be any collection, eg. a vector. (hc/xform [:X :Y] :X 1 :Y "hi") => [1 "hi"]). What might be better is to not use the ':field' example at all (bringing in too many orthogonal issues), but something totally artificial. So, maybe something like

In a template we might have a field foo with value :BAR, as in {... :foo :BAR ...}. When we apply hc/xformto the template,:foo's value :BARwill be replaced by the value of:BARin the current substitution map. The value of:BARin the current substitution map could come from in line arguments, such as(hc/xform {... :foo :BAR ...} :BAR "hi" ...)or from the default substitution map if:BAR` is added there, or from template local defaults.

Or something along those lines.

Copy link
Author

@mars0i mars0i Jan 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jsa-aerial. I'll think about all of that. There are often tradeoffs between introducing new ideas and being accurate. (When I'm teaching, I sometimes tell students "What I just said isn't exactly correct, but it's close enough for now. You can take the advanced course to find out more.") I don't want to mislead, and I want to try help someone who doesn't yet have the big picture to take a step into it.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @mars0i, that's a good point about introduction vs 'detail/accuracy'. Since this is basically the reference document, I wonder if a nice way of "threading this needle" would be to have a simple introductory text as well. Or probably even the thing a new person would reach for first. That does seem like something that would be very valuable. At the moment, I am drowning in some other things (including more documentation for something else), so I don't think I would be able to get to it soon. Many thanks for these helpful ideas!

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, on the 'intro' front, have you seen Kira McClean's Visualizing Data with Hanami talk from re:Clojure? It is really good - better than any I've done :-/. Hmmm, now I think of it, I should put that in the README somewhere.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in a position to write a full intro document. Even if I had time, I don't feel I understand enough yet--I think you've seen evidence of that already. I still think I can probably come up with a version of that substitution example paragraph that will help someone get in to the ballpark without misleading, though.

(I attended Kira McClean's talk, and yes, it was very helpful, and it got me started--though for me at that point it was a lot at once. I'd had no experience at all with hanami, Vega-Lite, or clerk--which one needed to run to follow along (or with any grammar of graphics lib--I use Lattice not ggplot with R--or any notebook!). I'm sure I'd learn more if I went back and watched the video now, though, with pauses if need be.)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would have been a lot to onboard all at once!


A more complex example would be the field and value `:encoding :ENCODING` in the predefined subcomponent `ht/view-base` which lays out the structure of a Vega-Lite _view_. As before `:ENCODING` will be replaced during transformation by the value of `:ENCODING` in the substitution map. However, the default value of `:ENCODING` is the predefined subcomponent `ht/xy-encoding`. This value is a map describing the structure of a view's `x-y` encodings and contains many fields with their own substitution keys. So, to produce a final value, `ht/xy-encoding` is recursively transformed so that the final value of `:encoding` is a fully realized `x-y` encoding for the view being processed. `ht/view-base` has several other such fields and is itself recursively transformed in the context of the current substitution map. And its final value will be the base of a chart, such as a line chart (`ht/line-chart`) or area chart (`ht/area-chart`), or some new plot/chart/layout/etc of your own for some domain specific application.

Expand Down