2 This notebook is about using the "zipper" with joy datastructures. See
4 entry <https://en.wikipedia.org/wiki/Zipper_%28data_structure%29>`__ or
5 the original paper: `"FUNCTIONAL PEARL The Zipper" by GĂ©rard
6 Huet <https://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced-fp/docs/huet-zipper.pdf>`__
8 Given a datastructure on the stack we can navigate through it, modify
9 it, and rebuild it using the "zipper" technique.
16 from notebook_preamble import J, V, define
21 In Joypy there aren't any complex datastructures, just ints, floats,
22 strings, Symbols (strings that are names of functions) and sequences
23 (aka lists, aka quoted literals, aka aggregates, etc...), but we can
25 `trees <https://en.wikipedia.org/wiki/Tree_%28data_structure%29>`__ out
30 J('[1 [2 [3 4 25 6] 7] 8]')
35 [1 [2 [3 4 25 6] 7] 8]
41 Zippers work by keeping track of the current item, the already-seen
42 items, and the yet-to-be seen items as you traverse a datastructure (the
43 datastructure used to keep track of these items is the zipper.)
45 In Joy we can do this with the following words:
49 z-down == [] swap uncons swap
50 z-up == swons swap shunt
51 z-right == [swons] cons dip uncons swap
52 z-left == swons [uncons swap] dip swap
54 Let's use them to change 25 into 625. The first time a word is used I
55 show the trace so you can see how it works. If we were going to use
56 these a lot it would make sense to write Python versions for efficiency,
61 define('z-down == [] swap uncons swap')
62 define('z-up == swons swap shunt')
63 define('z-right == [swons] cons dip uncons swap')
64 define('z-left == swons [uncons swap] dip swap')
68 V('[1 [2 [3 4 25 6] 7] 8] z-down')
73 . [1 [2 [3 4 25 6] 7] 8] z-down
74 [1 [2 [3 4 25 6] 7] 8] . z-down
75 [1 [2 [3 4 25 6] 7] 8] . [] swap uncons swap
76 [1 [2 [3 4 25 6] 7] 8] [] . swap uncons swap
77 [] [1 [2 [3 4 25 6] 7] 8] . uncons swap
78 [] 1 [[2 [3 4 25 6] 7] 8] . swap
79 [] [[2 [3 4 25 6] 7] 8] 1 .
84 V('[] [[2 [3 4 25 6] 7] 8] 1 z-right')
89 . [] [[2 [3 4 25 6] 7] 8] 1 z-right
90 [] . [[2 [3 4 25 6] 7] 8] 1 z-right
91 [] [[2 [3 4 25 6] 7] 8] . 1 z-right
92 [] [[2 [3 4 25 6] 7] 8] 1 . z-right
93 [] [[2 [3 4 25 6] 7] 8] 1 . [swons] cons dip uncons swap
94 [] [[2 [3 4 25 6] 7] 8] 1 [swons] . cons dip uncons swap
95 [] [[2 [3 4 25 6] 7] 8] [1 swons] . dip uncons swap
96 [] . 1 swons [[2 [3 4 25 6] 7] 8] uncons swap
97 [] 1 . swons [[2 [3 4 25 6] 7] 8] uncons swap
98 [] 1 . swap cons [[2 [3 4 25 6] 7] 8] uncons swap
99 1 [] . cons [[2 [3 4 25 6] 7] 8] uncons swap
100 [1] . [[2 [3 4 25 6] 7] 8] uncons swap
101 [1] [[2 [3 4 25 6] 7] 8] . uncons swap
102 [1] [2 [3 4 25 6] 7] [8] . swap
103 [1] [8] [2 [3 4 25 6] 7] .
108 J('[1] [8] [2 [3 4 25 6] 7] z-down')
113 [1] [8] [] [[3 4 25 6] 7] 2
118 J('[1] [8] [] [[3 4 25 6] 7] 2 z-right')
123 [1] [8] [2] [7] [3 4 25 6]
128 J('[1] [8] [2] [7] [3 4 25 6] z-down')
133 [1] [8] [2] [7] [] [4 25 6] 3
138 J('[1] [8] [2] [7] [] [4 25 6] 3 z-right')
143 [1] [8] [2] [7] [3] [25 6] 4
148 J('[1] [8] [2] [7] [3] [25 6] 4 z-right')
153 [1] [8] [2] [7] [4 3] [6] 25
158 J('[1] [8] [2] [7] [4 3] [6] 25 sqr')
163 [1] [8] [2] [7] [4 3] [6] 625
168 V('[1] [8] [2] [7] [4 3] [6] 625 z-up')
173 . [1] [8] [2] [7] [4 3] [6] 625 z-up
174 [1] . [8] [2] [7] [4 3] [6] 625 z-up
175 [1] [8] . [2] [7] [4 3] [6] 625 z-up
176 [1] [8] [2] . [7] [4 3] [6] 625 z-up
177 [1] [8] [2] [7] . [4 3] [6] 625 z-up
178 [1] [8] [2] [7] [4 3] . [6] 625 z-up
179 [1] [8] [2] [7] [4 3] [6] . 625 z-up
180 [1] [8] [2] [7] [4 3] [6] 625 . z-up
181 [1] [8] [2] [7] [4 3] [6] 625 . swons swap shunt
182 [1] [8] [2] [7] [4 3] [6] 625 . swap cons swap shunt
183 [1] [8] [2] [7] [4 3] 625 [6] . cons swap shunt
184 [1] [8] [2] [7] [4 3] [625 6] . swap shunt
185 [1] [8] [2] [7] [625 6] [4 3] . shunt
186 [1] [8] [2] [7] [3 4 625 6] .
191 J('[1] [8] [2] [7] [3 4 625 6] z-up')
196 [1] [8] [2 [3 4 625 6] 7]
201 J('[1] [8] [2 [3 4 625 6] 7] z-up')
206 [1 [2 [3 4 625 6] 7] 8]
209 ``dip`` and ``infra``
210 ---------------------
212 In Joy we have the ``dip`` and ``infra`` combinators which can "target"
213 or "address" any particular item in a Joy tree structure.
217 V('[1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra')
222 . [1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra
223 [1 [2 [3 4 25 6] 7] 8] . [[[[[[sqr] dipd] infra] dip] infra] dip] infra
224 [1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] . infra
225 8 [2 [3 4 25 6] 7] 1 . [[[[[sqr] dipd] infra] dip] infra] dip [] swaack
226 8 [2 [3 4 25 6] 7] 1 [[[[[sqr] dipd] infra] dip] infra] . dip [] swaack
227 8 [2 [3 4 25 6] 7] . [[[[sqr] dipd] infra] dip] infra 1 [] swaack
228 8 [2 [3 4 25 6] 7] [[[[sqr] dipd] infra] dip] . infra 1 [] swaack
229 7 [3 4 25 6] 2 . [[[sqr] dipd] infra] dip [8] swaack 1 [] swaack
230 7 [3 4 25 6] 2 [[[sqr] dipd] infra] . dip [8] swaack 1 [] swaack
231 7 [3 4 25 6] . [[sqr] dipd] infra 2 [8] swaack 1 [] swaack
232 7 [3 4 25 6] [[sqr] dipd] . infra 2 [8] swaack 1 [] swaack
233 6 25 4 3 . [sqr] dipd [7] swaack 2 [8] swaack 1 [] swaack
234 6 25 4 3 [sqr] . dipd [7] swaack 2 [8] swaack 1 [] swaack
235 6 25 . sqr 4 3 [7] swaack 2 [8] swaack 1 [] swaack
236 6 25 . dup mul 4 3 [7] swaack 2 [8] swaack 1 [] swaack
237 6 25 25 . mul 4 3 [7] swaack 2 [8] swaack 1 [] swaack
238 6 625 . 4 3 [7] swaack 2 [8] swaack 1 [] swaack
239 6 625 4 . 3 [7] swaack 2 [8] swaack 1 [] swaack
240 6 625 4 3 . [7] swaack 2 [8] swaack 1 [] swaack
241 6 625 4 3 [7] . swaack 2 [8] swaack 1 [] swaack
242 7 [3 4 625 6] . 2 [8] swaack 1 [] swaack
243 7 [3 4 625 6] 2 . [8] swaack 1 [] swaack
244 7 [3 4 625 6] 2 [8] . swaack 1 [] swaack
245 8 [2 [3 4 625 6] 7] . 1 [] swaack
246 8 [2 [3 4 625 6] 7] 1 . [] swaack
247 8 [2 [3 4 625 6] 7] 1 [] . swaack
248 [1 [2 [3 4 625 6] 7] 8] .
251 If you read the trace carefully you'll see that about half of it is the
252 ``dip`` and ``infra`` combinators de-quoting programs and "digging" into
253 the subject datastructure. Instead of maintaining temporary results on
254 the stack they are pushed into the pending expression (continuation).
255 When ``sqr`` has run the rest of the pending expression rebuilds the
261 Imagine a function ``Z`` that accepts a sequence of ``dip`` and
262 ``infra`` combinators, a quoted program ``[Q]``, and a datastructure to
263 work on. It would effectively execute the quoted program as if it had
264 been embedded in a nested series of quoted programs, e.g.:
268 [...] [Q] [dip dip infra dip infra dip infra] Z
269 -------------------------------------------------------------
270 [...] [[[[[[[Q] dip] dip] infra] dip] infra] dip] infra
273 The ``Z`` function isn't hard to make.
277 define('Z == [[] cons cons] step i')
279 Here it is in action in a simplified scenario.
291 1 [2 3 4] . [[] cons cons] step i
292 1 [2 3 4] [[] cons cons] . step i
293 1 2 [[] cons cons] . i [3 4] [[] cons cons] step i
294 1 2 . [] cons cons [3 4] [[] cons cons] step i
295 1 2 [] . cons cons [3 4] [[] cons cons] step i
296 1 [2] . cons [3 4] [[] cons cons] step i
297 [1 2] . [3 4] [[] cons cons] step i
298 [1 2] [3 4] . [[] cons cons] step i
299 [1 2] [3 4] [[] cons cons] . step i
300 [1 2] 3 [[] cons cons] . i [4] [[] cons cons] step i
301 [1 2] 3 . [] cons cons [4] [[] cons cons] step i
302 [1 2] 3 [] . cons cons [4] [[] cons cons] step i
303 [1 2] [3] . cons [4] [[] cons cons] step i
304 [[1 2] 3] . [4] [[] cons cons] step i
305 [[1 2] 3] [4] . [[] cons cons] step i
306 [[1 2] 3] [4] [[] cons cons] . step i
307 [[1 2] 3] 4 [[] cons cons] . i i
308 [[1 2] 3] 4 . [] cons cons i
309 [[1 2] 3] 4 [] . cons cons i
310 [[1 2] 3] [4] . cons i
317 And here it is doing the main thing.
321 J('[1 [2 [3 4 25 6] 7] 8] [sqr] [dip dip infra dip infra dip infra] Z')
326 [1 [2 [3 4 625 6] 7] 8]
332 Because we are only using two combinators we could replace the list with
333 a string made from only two characters.
337 [...] [Q] 'ddididi' Zstr
338 -------------------------------------------------------------
339 [...] [[[[[[[Q] dip] dip] infra] dip] infra] dip] infra
341 The string can be considered a name or address for an item in the
342 subject datastructure.
344 Determining the right "path" for an item in a tree.
345 ---------------------------------------------------
347 It's easy to read off (in reverse) the right sequence of "d" and "i"
348 from the subject datastructure: