From c9aff05fa2b858bd5563c4cfb8aaa9c6e7e6ae3a Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 1 Oct 2019 21:12:06 +0200 Subject: [PATCH 1/2] specify setproperties more precisely #11 --- src/ConstructionBase.jl | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/ConstructionBase.jl b/src/ConstructionBase.jl index 293858e..0cfea33 100644 --- a/src/ConstructionBase.jl +++ b/src/ConstructionBase.jl @@ -126,8 +126,41 @@ S("A", 2, "cc") # Overloading -**WARNING** The signature `setproperties(obj::MyType; kw...)` should never be overloaded. -Instead `setproperties(obj::MyType, patch::NamedTuple)` should be overloaded. +**WARNING** The signature `setproperties(obj::MyType; kw...)` should never be overloaded. Instead `setproperties(obj::MyType, patch::NamedTuple)` should be overloaded. + +# Specification + +`setproperties` guarantees a couple of invariants. When overloading it, the user is responsible for ensuring them: + +1. Purity: `setproperties` is supposed to have no side effects. In particular `setproperties(obj, patch::NamedTuple)` may not mutate `obj`. +2. Relation to `propertynames` and `fieldnames`: `setproperties` relates to `propertynames` and `getproperty`, not to `fieldnames` and `getfield`. +This means that any subset `p₁, p₂, ..., pₙ` of `propertynames(obj)` is a valid set of properties, with respect to which the lens laws below must hold. +3. `setproperties` should satisfy the lens laws: +For any valid set of properties `p₁, p₂, ..., pₙ`, following equalities must hold: + +* You get what you set. + +let obj′ = setproperties(obj, ($p₁=v₁, $p₂=v₂, ..., $pₙ=vₙ)) + @assert obj′.$p₁ == v₁ + @assert obj′.$p₂ == v₂ + ... + @assert obj′.$pₙ == vₙ +end + +* Setting what was already there changes nothing: + +`@assert setproperties(obj, ($p₁=obj.$p₁, $p₂=obj.$p₂, ..., $pₙ=obj.$pₙ)) == obj` + +* The last set wins: +```julia +let obj′ = setproperties(obj, ($p₁=v₁, $p₂=v₂, ..., $pₙ=vₙ)), + obj′′ = setproperties(obj′, ($p₁=w₁, $p₂=w₂, ..., $pₙ=wₙ)) + @assert obj′′.$p₁ == w₁ + @assert obj′′.$p₂ == w₂ + ... + @assert obj′′.$pₙ == wₙ +end +``` """ function setproperties end From c549745066f20160fd68bab46176400be0826f3f Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 1 Oct 2019 21:45:09 +0200 Subject: [PATCH 2/2] fix setproperties docstring --- src/ConstructionBase.jl | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/ConstructionBase.jl b/src/ConstructionBase.jl index 0cfea33..129da09 100644 --- a/src/ConstructionBase.jl +++ b/src/ConstructionBase.jl @@ -140,25 +140,29 @@ For any valid set of properties `p₁, p₂, ..., pₙ`, following equalities mu * You get what you set. -let obj′ = setproperties(obj, ($p₁=v₁, $p₂=v₂, ..., $pₙ=vₙ)) - @assert obj′.$p₁ == v₁ - @assert obj′.$p₂ == v₂ +```julia +let obj′ = setproperties(obj, (\$p₁=v₁, \$p₂=v₂, ..., \$pₙ=vₙ)) + @assert obj′.\$p₁ == v₁ + @assert obj′.\$p₂ == v₂ ... - @assert obj′.$pₙ == vₙ + @assert obj′.\$pₙ == vₙ end +``` * Setting what was already there changes nothing: -`@assert setproperties(obj, ($p₁=obj.$p₁, $p₂=obj.$p₂, ..., $pₙ=obj.$pₙ)) == obj` +```julia +@assert setproperties(obj, (\$p₁=obj.\$p₁, \$p₂=obj.\$p₂, ..., \$pₙ=obj.\$pₙ)) == obj +``` * The last set wins: ```julia -let obj′ = setproperties(obj, ($p₁=v₁, $p₂=v₂, ..., $pₙ=vₙ)), - obj′′ = setproperties(obj′, ($p₁=w₁, $p₂=w₂, ..., $pₙ=wₙ)) - @assert obj′′.$p₁ == w₁ - @assert obj′′.$p₂ == w₂ +let obj′ = setproperties(obj, (\$p₁=v₁, \$p₂=v₂, ..., \$pₙ=vₙ)), + obj′′ = setproperties(obj′, (\$p₁=w₁, \$p₂=w₂, ..., \$pₙ=wₙ)) + @assert obj′′.\$p₁ == w₁ + @assert obj′′.\$p₂ == w₂ ... - @assert obj′′.$pₙ == wₙ + @assert obj′′.\$pₙ == wₙ end ``` """