@@ -249,8 +249,36 @@ function modify(f, obj, w::If)
249
249
end
250
250
end
251
251
252
+ abstract type ObjectMap end
253
+
254
+ OpticStyle (:: Type{<:ObjectMap} ) = ModifyBased ()
255
+ modify (f, o, optic:: ObjectMap ) = mapobject (f, o, optic, Construct, nothing )
256
+
257
+ """
258
+ Properties()
259
+
260
+ Access all properties of an objects.
261
+
262
+ ```jldoctest
263
+ julia> using Accessors
264
+
265
+ julia> obj = (a=1, b=2, c=3)
266
+ (a = 1, b = 2, c = 3)
267
+
268
+ julia> set(obj, Properties(), "hi")
269
+ (a = "hi", b = "hi", c = "hi")
270
+
271
+ julia> modify(x -> 2x, obj, Properties())
272
+ (a = 2, b = 4, c = 6)
273
+ ```
274
+ Based on [`mapobject`](@ref).
275
+
276
+ $EXPERIMENTAL
277
+ """
278
+ struct Properties <: ObjectMap end
279
+
252
280
"""
253
- mapproperties (f, obj)
281
+ mapobject (f, obj)
254
282
255
283
Construct a copy of `obj`, with each property replaced by
256
284
the result of applying `f` to it.
@@ -260,82 +288,63 @@ julia> using Accessors
260
288
261
289
julia> obj = (a=1, b=2);
262
290
263
- julia> Accessors.mapproperties (x -> x+1, obj)
291
+ julia> Accessors.mapobject (x -> x+1, obj)
264
292
(a = 2, b = 3)
265
293
```
266
294
$EXPERIMENTAL
267
295
"""
268
- function mapproperties (f, obj:: O , handler= Construct () , itr:: Nothing = nothing ) where O
296
+ function mapobject (f, obj:: O , :: Properties , handler, itr:: Nothing ) where O
269
297
# TODO move this helper elsewhere?
270
298
pnames = propertynames (obj)
271
299
if isempty (pnames)
272
300
return obj
273
301
else
274
- ctor = constructorof (typeof (obj))
275
302
new_props = map (pnames) do p
276
303
f (getproperty (obj, p))
277
304
end
278
305
ctr = _constructor (handler, O)
279
306
return ctr (new_props... )
280
307
end
281
308
end
282
- function mapproperties (f, obj:: O , handler, itr:: Int ) where O
309
+ function mapobject (f, obj:: O , :: Properties , handler, itr:: Int ) where O
283
310
pnames = propertynames (obj)
284
311
if isempty (pnames)
285
- return _maybeitr ( obj, itr)
312
+ return obj, itr
286
313
else
287
314
# TODO : this is too slow
288
315
new_props, itr = reduce (pnames; init= ((), itr)) do (vals, itr), p
289
316
val, itr = f (getproperty (obj, p), itr)
290
317
(vals... , val), itr
291
318
end
292
319
ctr = _constructor (handler, O)
293
- return _maybeitr ( ctr (new_props... ), itr)
320
+ return ctr (new_props... ), itr
294
321
end
295
322
end
296
323
297
324
"""
298
- Properties ()
325
+ Fields ()
299
326
300
- Access all properties of an objects.
327
+ Access all fields of an objects.
301
328
302
329
```jldoctest
303
330
julia> using Accessors
304
331
305
332
julia> obj = (a=1, b=2, c=3)
306
333
(a = 1, b = 2, c = 3)
307
334
308
- julia> set(obj, Properties (), "hi")
335
+ julia> set(obj, Fields (), "hi")
309
336
(a = "hi", b = "hi", c = "hi")
310
337
311
- julia> modify(x -> 2x, obj, Properties ())
338
+ julia> modify(x -> 2x, obj, Fields ())
312
339
(a = 2, b = 4, c = 6)
313
340
```
314
- Based on [`mapproperties `](@ref).
341
+ Based on [`mapfields `](@ref).
315
342
316
343
$EXPERIMENTAL
317
344
"""
318
- struct Properties end
319
- OpticStyle (:: Type{<:Properties} ) = ModifyBased ()
320
- modify (f, o, :: Properties ) = mapproperties (f, o)
321
-
322
- """
323
- mapfields(f, obj)
324
-
325
- Construct a copy of `obj`, with each fields replaced by
326
- the result of applying `f` to it.
327
-
328
- ```jldoctest
329
- julia> using Accessors
330
-
331
- julia> obj = (a=1, b=2);
345
+ struct Fields <: ObjectMap end
332
346
333
- julia> Accessors.mapfields(x -> x+1, obj)
334
- (a = 2, b = 3)
335
- ```
336
- $EXPERIMENTAL
337
- """
338
- @generated function mapfields (f, obj:: O , handler:: H = Construct (), itr:: I = nothing ) where {O,H,I}
347
+ @generated function mapobject (f, obj:: O , :: Fields , handler:: H = Construct (), itr:: I = nothing ) where {O,H,I}
339
348
# TODO : This is how Flatten.jl works, but it's not really
340
349
# correct use of ConstructionBase as it assumers properties=fields
341
350
fnames = fieldnames (O)
385
394
_maybeitr (x, :: Nothing ) = x
386
395
_maybeitr (x, itr) = x, itr
387
396
388
- """
389
- Fields()
390
-
391
- Access all fields of an objects.
392
-
393
- ```jldoctest
394
- julia> using Accessors
395
-
396
- julia> obj = (a=1, b=2, c=3)
397
- (a = 1, b = 2, c = 3)
398
-
399
- julia> set(obj, Fields(), "hi")
400
- (a = "hi", b = "hi", c = "hi")
401
-
402
- julia> modify(x -> 2x, obj, Fields())
403
- (a = 2, b = 4, c = 6)
404
- ```
405
- Based on [`mapfields`](@ref).
406
-
407
- $EXPERIMENTAL
408
- """
409
- struct Fields end
410
- OpticStyle (:: Type{<:Fields} ) = ModifyBased ()
411
- modify (f, o, :: Fields ) = mapfields (f, o)
412
-
413
397
"""
414
398
Recursive(descent_condition, optic)
415
399
@@ -484,11 +468,10 @@ Base.@propagate_inbounds function set(obj, lens::DynamicIndexLens, val)
484
468
end
485
469
486
470
"""
487
- Query(select, ignore )
471
+ Query(select, descend )
488
472
489
- Query an object recursively, choosing fields based on the single-argument
490
- function `select` and ignoring objects based on another single-argument
491
- function `ignore`.
473
+ Query an object recursively, choosing fields when `select`
474
+ returns `true`, and descending when `descend`.
492
475
493
476
```jldoctest
494
477
julia> using Accessors
@@ -515,43 +498,37 @@ end
515
498
Query (select, descend = x -> true ) = Query (select, descend, Fields ())
516
499
Query (; select= Any, descend= x -> true , optic= Fields ()) = Query (select, descend, optic)
517
500
518
- _inner (optic:: ComposedOptic ) = optic. inner
519
- _inner (optic:: Fields ) = optic
520
- _inner (optic:: Properties ) = optic
521
-
522
501
function (q:: Query )(obj)
523
- _query (obj, _inner (q. optic), Splat (), nothing ) do o
502
+ mapobject (obj, _inner (q. optic), Splat (), nothing ) do o
524
503
if q. select_condition (o)
525
504
(_getouter (o, q. optic),)
526
505
elseif q. descent_condition (o)
527
- q (o)
506
+ q (o) # also a tuple
528
507
else
529
508
()
530
509
end
531
510
end
532
511
end
533
512
534
- _getouter (o, optic:: ComposedOptic ) = optic. outer (o)
535
- _getouter (o, optic) = o
536
-
537
- _set (obj, q:: Query , val, :: SetBased ) = _setquery (obj, q:: Query , (val, 1 ))[1 ]
513
+ set (obj, q:: Query , vals) = _set (obj, q:: Query , (vals, 1 ))[1 ]
538
514
539
- function _setquery (obj, q:: Query , (val , itr))
540
- _query (obj, _inner (q. optic), Construct (), itr) do o, itr
515
+ function _set (obj, q:: Query , (vals , itr))
516
+ mapobject (obj, _inner (q. optic), Construct (), itr) do o, itr
541
517
if q. select_condition (o)
542
- _setouter (o, q. optic, val [itr]), itr + 1
518
+ _setouter (o, q. optic, vals [itr]), itr + 1
543
519
elseif q. descent_condition (o)
544
- _setquery (o, q, (val , itr))
520
+ _set (o, q, (vals , itr))
545
521
else
546
522
o, itr
547
523
end
548
524
end
549
525
end
550
526
551
- _setouter (o, optic:: ComposedOptic , v) = set (o, optic. outer, v)
552
- _setouter (o, optic, v) = v
553
-
554
527
modify (f, obj, q:: Query ) = set (obj, q, map (f, q (obj)))
555
528
556
- _query (f, o, :: Fields , handler, itr) = mapfields (f, o, handler, itr)
557
- _query (f, o, :: Properties , handler, itr) = mapproperties (f, o, handler, itr)
529
+ _inner (optic:: ComposedOptic ) = optic. inner
530
+ _inner (optic) = optic
531
+ _getouter (o, optic:: ComposedOptic ) = optic. outer (o)
532
+ _getouter (o, optic) = o
533
+ _setouter (o, optic:: ComposedOptic , v) = set (o, optic. outer, v)
534
+ _setouter (o, optic, v) = v
0 commit comments