@@ -111,6 +111,73 @@ object BidirectionalVarOperatorTests extends TestSuite {
111
111
assert(zipcode.now == 6 )
112
112
}
113
113
114
+ " zoomed Var chained" - {
115
+ import Ctx .Owner .Unsafe ._
116
+
117
+ case class Company (name : String , zipcode : Int )
118
+ case class Employee (name : String , company : Company )
119
+
120
+ val employee = Var (Employee (" jules" , Company (" wules" , 7 )))
121
+ val company = employee.zoom(_.company)((old, value) => old.copy(company = value))
122
+ val zipcode = company.zoom(_.zipcode)((old, value) => old.copy(zipcode = value))
123
+
124
+ assert(company.now == Company (" wules" , 7 ))
125
+ assert(employee.now == Employee (" jules" , Company (" wules" , 7 )))
126
+ assert(zipcode.now == 7 )
127
+
128
+ zipcode() = 8
129
+ assert(company.now == Company (" wules" , 8 ))
130
+ assert(employee.now == Employee (" jules" , Company (" wules" , 8 )))
131
+ assert(zipcode.now == 8 )
132
+
133
+ employee() = Employee (" gula" , Company (" bori" , 6 ))
134
+ assert(company.now == Company (" bori" , 6 ))
135
+ assert(employee.now == Employee (" gula" , Company (" bori" , 6 )))
136
+ assert(zipcode.now == 6 )
137
+
138
+ company() = Company (" borislav" , 13 )
139
+ assert(company.now == Company (" borislav" , 13 ))
140
+ assert(employee.now == Employee (" gula" , Company (" borislav" , 13 )))
141
+ assert(zipcode.now == 13 )
142
+ }
143
+
144
+ " zoomed Var chained with observer" - {
145
+ import Ctx .Owner .Unsafe ._
146
+
147
+ case class Company (name : String , zipcode : Int )
148
+ case class Employee (name : String , company : Company )
149
+
150
+ val employee = Var (Employee (" jules" , Company (" wules" , 7 )))
151
+ val company = employee.zoom(_.company)((old, value) => old.copy(company = value))
152
+ val zipcode = company.zoom(_.zipcode)((old, value) => old.copy(zipcode = value))
153
+
154
+ var employeeNow = employee.now
155
+ employee.foreach { employeeNow = _ }
156
+
157
+ assert(company.now == Company (" wules" , 7 ))
158
+ assert(employeeNow == Employee (" jules" , Company (" wules" , 7 )))
159
+ assert(employee.now == Employee (" jules" , Company (" wules" , 7 )))
160
+ assert(zipcode.now == 7 )
161
+
162
+ zipcode() = 8
163
+ assert(company.now == Company (" wules" , 8 ))
164
+ assert(employeeNow == Employee (" jules" , Company (" wules" , 8 )))
165
+ assert(employee.now == Employee (" jules" , Company (" wules" , 8 )))
166
+ assert(zipcode.now == 8 )
167
+
168
+ employee() = Employee (" gula" , Company (" bori" , 6 ))
169
+ assert(company.now == Company (" bori" , 6 ))
170
+ assert(employeeNow == Employee (" gula" , Company (" bori" , 6 )))
171
+ assert(employee.now == Employee (" gula" , Company (" bori" , 6 )))
172
+ assert(zipcode.now == 6 )
173
+
174
+ company() = Company (" borislav" , 13 )
175
+ assert(company.now == Company (" borislav" , 13 ))
176
+ assert(employeeNow == Employee (" gula" , Company (" borislav" , 13 )))
177
+ assert(employee.now == Employee (" gula" , Company (" borislav" , 13 )))
178
+ assert(zipcode.now == 13 )
179
+ }
180
+
114
181
" isomorphic Var function calls" - {
115
182
import Ctx .Owner .Unsafe ._
116
183
@@ -205,28 +272,100 @@ object BidirectionalVarOperatorTests extends TestSuite {
205
272
assert(selectedItem.now == Some (4 ))
206
273
}
207
274
208
- " mapRead then zoom" - {
275
+ " mapRead observer" - {
276
+ import Ctx .Owner .Unsafe ._
277
+
278
+ val list = Var (List (1 , 2 , 3 ))
279
+ val selectedItem = Var [Option [Int ]](Some (1 )).mapRead {
280
+ selected => selected().filter(list() contains _)
281
+ }
282
+ var myNow : Option [Int ] = None
283
+ selectedItem.foreach { myNow = _ }
284
+
285
+ assert(myNow == Some (1 ))
286
+
287
+ selectedItem() = Some (4 )
288
+ assert(myNow == None )
289
+
290
+ list.update(4 :: _)
291
+ assert(myNow == Some (4 ))
292
+ }
293
+
294
+ " mapRead then zoom (write into outer)" - {
209
295
import Ctx .Owner .Unsafe ._
210
- case class Store (selected: Option [Int ])
296
+ case class SelectedWrapper (selected: Option [Int ])
211
297
212
298
val list = Var (List (1 , 2 , 3 ))
213
- val store = Var [Store ]( Store (Some (1 ))).mapRead {
214
- store => store ().copy(selected = store ().selected.filter(list() contains _))
299
+ val selWrapper = Var [SelectedWrapper ]( SelectedWrapper (Some (1 ))).mapRead {
300
+ selWrapper => selWrapper ().copy(selected = selWrapper ().selected.filter(list() contains _))
215
301
}
216
- val selectedItem = store .zoom(_.selected)((store ,selected) => store .copy(selected = selected))
302
+ val selectedItem = selWrapper .zoom(_.selected)((selWrapper ,selected) => selWrapper .copy(selected = selected))
217
303
304
+ assert(selWrapper.now.selected == Some (1 ))
218
305
assert(selectedItem.now == Some (1 ))
219
306
220
- selectedItem() = Some (3 )
307
+ selWrapper() = SelectedWrapper (Some (4 ))
308
+ assert(selWrapper.now.selected == None )
221
309
assert(selectedItem.now == None ) // fail: is Some(3) ...
222
310
223
311
list.update(4 :: _)
224
- assert(selectedItem.now == None ) // fail: still is Some(3)
312
+ assert(selWrapper.now.selected == Some (4 ))
313
+ assert(selectedItem.now == Some (4 )) // fail: still is Some(3)
314
+
315
+ selWrapper() = SelectedWrapper (Some (4 ))
316
+ assert(selWrapper.now.selected == Some (4 ))
317
+ assert(selectedItem.now == Some (4 ))
318
+ }
319
+
320
+ " mapRead then zoom (write into zoomed)" - {
321
+ import Ctx .Owner .Unsafe ._
322
+ case class SelectedWrapper (selected: Option [Int ])
323
+
324
+ val list = Var (List (1 , 2 , 3 ))
325
+ val selWrapper = Var [SelectedWrapper ](SelectedWrapper (Some (1 )))
326
+ val selWrapperFiltered = selWrapper.mapRead {
327
+ selWrapper => selWrapper().copy(selected = selWrapper().selected.filter(list() contains _))
328
+ }
329
+ val selectedItem = selWrapperFiltered.zoom(_.selected)((selWrapper,selected) => selWrapper.copy(selected = selected))
330
+
331
+ assert(selWrapper.now.selected == Some (1 ))
332
+ assert(selWrapperFiltered.now.selected == Some (1 ))
333
+ assert(selectedItem.now == Some (1 ))
334
+
335
+ selectedItem() = Some (4 ) // write indirectly into selWrapper
336
+ assert(selWrapper.now.selected == Some (4 ))
337
+ assert(selWrapperFiltered.now.selected == None )
338
+ assert(selectedItem.now == None ) // fail: is Some(3) ...
339
+
340
+ list.update(4 :: _)
341
+ assert(selWrapper.now.selected == Some (4 ))
342
+ assert(selWrapperFiltered.now.selected == Some (4 ))
343
+ assert(selectedItem.now == Some (4 )) // fail: still is Some(3)
225
344
226
345
selectedItem() = Some (4 )
346
+ assert(selWrapper.now.selected == Some (4 ))
347
+ assert(selWrapperFiltered.now.selected == Some (4 ))
227
348
assert(selectedItem.now == Some (4 ))
228
349
}
229
350
351
+ " imap then zoom (write into zoomed)" - {
352
+ import Ctx .Owner .Unsafe ._
353
+ case class Wrapper (x: Int )
354
+ val base = Var (Wrapper (5 ))
355
+ val imapped = base.imap(w => w.copy(x = w.x + 1 ))(w => w.copy(x = w.x - 1 ))
356
+ val zoomed = imapped.zoom(_.x)( (old, value) => old.copy(x = value))
357
+
358
+ zoomed() = 1
359
+ assert(zoomed.now == 1 )
360
+ assert(imapped.now == Wrapper (1 ))
361
+ assert(base.now == Wrapper (0 ))
362
+
363
+ zoomed() = 2
364
+ assert(zoomed.now == 2 )
365
+ assert(imapped.now == Wrapper (2 ))
366
+ assert(base.now == Wrapper (1 ))
367
+ }
368
+
230
369
" mapRead function calls" - {
231
370
import Ctx .Owner .Unsafe ._
232
371
0 commit comments