@@ -133,6 +133,8 @@ struct ConstructIfChanged{C}
133133 constructor:: C
134134end
135135
136+ _constructor (x, t) = _constructor (x. handler, t)
137+
136138# TODO what do we call these things?
137139struct Construct end
138140_constructor (:: Construct , :: Type{T} ) where T = constructorof (T)
@@ -249,6 +251,19 @@ function modify(f, obj, w::If)
249251 end
250252end
251253
254+ struct Select{C}
255+ select_condition:: C
256+ end
257+ OpticStyle (:: Type{<:If} ) = ModifyBased ()
258+
259+ function modify (f, obj, w:: If )
260+ if w. modify_condition (obj)
261+ (obj,)
262+ else
263+ ()
264+ end
265+ end
266+
252267"""
253268 mapproperties(f, obj)
254269
@@ -265,24 +280,31 @@ julia> Accessors.mapproperties(x -> x+1, obj)
265280```
266281$EXPERIMENTAL
267282"""
268- function mapproperties (f, obj:: O , handler = Construct () , itr= nothing ) where O
283+ function mapproperties (f, obj:: O , optic , itr:: Nothing = nothing ) where O
269284 # TODO move this helper elsewhere?
285+ pnames = propertynames (obj)
286+ if isempty (pnames)
287+ return obj
288+ else
289+ ctor = constructorof (typeof (obj))
290+ new_props = map (pnames) do p
291+ f (getproperty (obj, p))
292+ end
293+ ctr = _constructor (optic, O)
294+ return ctr (new_props... )
295+ end
296+ end
297+ function mapproperties (f, obj:: O , optic, itr:: Int ) where O
270298 pnames = propertynames (obj)
271299 if isempty (pnames)
272300 return _maybeitr (obj, itr)
273301 else
274302 # TODO : this is too slow
275303 new_props, itr = reduce (pnames; init= ((), itr)) do (vals, itr), p
276- prop = getproperty (obj, p)
277- if itr isa Nothing
278- val = f (prop)
279- (vals... , val), itr
280- else
281- val, itr = f (prop, itr)
282- (vals... , val), itr
283- end
304+ val, itr = f (getproperty (obj, p), itr)
305+ (vals... , val), itr
284306 end
285- ctr = _constructor (handler , O)
307+ ctr = _constructor (optic , O)
286308 return _maybeitr (ctr (new_props... ), itr)
287309 end
288310end
@@ -308,7 +330,10 @@ Based on [`mapproperties`](@ref).
308330
309331$EXPERIMENTAL
310332"""
311- struct Properties end
333+ struct Properties{H}
334+ handler:: H
335+ end
336+ Properties () = Properties (Construct ())
312337OpticStyle (:: Type{<:Properties} ) = ModifyBased ()
313338modify (f, o, :: Properties ) = mapproperties (f, o)
314339
@@ -328,7 +353,7 @@ julia> Accessors.mapfields(x -> x+1, obj)
328353```
329354$EXPERIMENTAL
330355"""
331- @generated function mapfields (f, obj:: O , handler :: H = Construct () , itr:: I = nothing ) where {O,H,I}
356+ @generated function mapfields (f, obj:: O , optic , itr:: I = nothing ) where {O,H,I}
332357 # TODO : This is how Flatten.jl works, but it's not really
333358 # correct use of ConstructionBase as it assumers properties=fields
334359 fnames = fieldnames (O)
@@ -350,23 +375,23 @@ $EXPERIMENTAL
350375 end
351376 new_prop_exp = Expr (:tuple , val_exps... )
352377 end
353- # ret = if H == MaybeConstruct
354- # quote
378+ ret = if H == MaybeConstruct
379+ quote
355380 # TODO : last type instability.
356381 # replace this with val => Changed(), val => Unchanged()
357382 # return values.
358383 #
359384 # Don't construct when we don't absolutely have to.
360385 # `constructorof` may not be defined for an object.
361- # if props === new_props
362- # return obj, itr
363- # else
364- # return _maybeitr($ctr(new_props...), itr)
365- # end
366- # end
367- # else
386+ if props === new_props
387+ return _maybeitr ( obj, itr)
388+ else
389+ return _maybeitr ($ ctr (new_props... ), itr)
390+ end
391+ end
392+ else
368393 ret = :(return _maybeitr ($ ctr (new_props... ), itr))
369- # end
394+ end
370395 quote
371396 props = $ prop_exp
372397 new_props = $ new_prop_exp
@@ -399,9 +424,12 @@ Based on [`mapfields`](@ref).
399424
400425$EXPERIMENTAL
401426"""
402- struct Fields end
427+ struct Fields{H}
428+ handler:: H
429+ end
430+ Fields () = Fields (Construct ())
403431OpticStyle (:: Type{<:Fields} ) = ModifyBased ()
404- modify (f, o, :: Fields ) = mapfields (f, o)
432+ modify (f, o, optic :: Fields ) = mapfields (f, o, optic )
405433
406434"""
407435 Recursive(descent_condition, optic)
@@ -505,7 +533,7 @@ struct Query{Select,Descend,Optic}
505533 descent_condition:: Descend
506534 optic:: Optic
507535end
508- Query (select, ignore = x -> true ) = Query (select, ignore , Fields ())
536+ Query (select, descend = x -> true ) = Query (select, descend , Fields ())
509537Query (; select= Any, descend= x -> true , optic= Fields ()) = Query (select, descend, optic)
510538
511539function (q:: Query )(obj)
@@ -534,6 +562,8 @@ function _setquery(obj, q::Query, (val, itr))
534562 end
535563end
536564
537- _query (f, o, :: Elements , handler, itr) = map (f, o)
538- _query (f, o, :: Fields , handler, itr) = mapfields (f, o, handler, itr)
539- _query (f, o, :: Properties , handler, itr) = mapproperties (f, o, handler, itr)
565+ modify (f, obj, q:: Query ) = set (obj, q, map (f, q (obj)))
566+
567+ _query (f, o, :: Elements , itr) = map (f, o)
568+ _query (f, o, :: Fields , itr) = mapfields (f, o, itr)
569+ _query (f, o, :: Properties , itr) = mapproperties (f, o, itr)
0 commit comments