Skip to content

Commit

Permalink
Merge pull request JuliaObjects#46 from aplavin/master
Browse files Browse the repository at this point in the history
add more functionlenses
  • Loading branch information
aplavin authored Jun 6, 2022
2 parents 049b151 + 508be17 commit 2961648
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 4 deletions.
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
name = "Accessors"
uuid = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
authors = ["Takafumi Arakaki <[email protected]>", "Jan Weidner <[email protected]> and contributors"]
version = "0.1.12"
version = "0.1.13"

[deps]
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
CompositionsBase = "a33af91c-f02d-484b-be07-31d278c5ca2b"
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Future = "9fa8497b-333b-5362-9e8d-4d0656e87820"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Expand All @@ -18,6 +19,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Compat = "3.18, 4"
CompositionsBase = "0.1"
ConstructionBase = "1.2"
InverseFunctions = "0.1.5"
MacroTools = "0.4.4, 0.5"
Requires = "0.5, 1.0"
StaticNumbers = "0.3"
Expand Down
1 change: 1 addition & 0 deletions src/Accessors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module Accessors
using MacroTools
using MacroTools: isstructdef, splitstructdef, postwalk
using Requires: @require
using InverseFunctions



Expand Down
20 changes: 20 additions & 0 deletions src/functionlenses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,30 @@ delete(path, ::typeof(dirname)) = basename(path)
set(x::Real, ::typeof(real), y) = y
set(x, ::typeof(real), y) = y + im*imag(x)
set(x, ::typeof(imag), y) = real(x) + im*y
set(x, ::typeof(angle), y) = abs(x) * cis(y)
set(x, ::typeof(abs), y) = y >= 0 ? y * sign(x) : throw(DomainError(y, "cannot set abs($x) to $y"))

set(arr, ::typeof(normalize), val) = norm(arr) * val
set(arr, ::typeof(norm), val) = val/norm(arr) * arr # should we check val is positive?

# functions supported by inverse()
# https://github.com/JuliaMath/InverseFunctions.jl/blob/master/src/inverse.jl
set(x, f::Union{
typeof.((
identity, inv, adjoint, transpose, conj,
!, +, -,
exp, log, exp2, log2, exp10, log10, expm1, log1p,
sqrt, cbrt, deg2rad, rad2deg,
))...,
Base.Fix1{typeof(+)}, Base.Fix2{typeof(+)},
Base.Fix1{typeof(-)}, Base.Fix2{typeof(-)},
Base.Fix1{typeof(*)}, Base.Fix2{typeof(*)},
Base.Fix1{typeof(/)}, Base.Fix2{typeof(/)},
Base.Fix1{typeof(\)}, Base.Fix2{typeof(\)},
Base.Fix1{typeof(^)}, Base.Fix2{typeof(^)},
Base.Fix1{typeof(log)}, Base.Fix2{typeof(log)},
}, y) = inverse(f)(y)

################################################################################
##### dates
################################################################################
Expand Down
6 changes: 3 additions & 3 deletions src/testing.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
using Test: @test
function test_getset_laws(lens, obj, val1, val2)
function test_getset_laws(lens, obj, val1, val2; cmp=(==))

# set ⨟ get
val = lens(obj)
@test set(obj, lens, val) == obj
@test cmp(set(obj, lens, val), obj)

# get ⨟ set
obj1 = set(obj, lens, val1)
@test lens(obj1) == val1
@test cmp(lens(obj1), val1)

# set idempotent
obj12 = set(obj1, lens, val2)
Expand Down
18 changes: 18 additions & 0 deletions test/test_functionlenses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,24 @@ end
@test 2.0 === @set real(1) = 2.0
@test 1.0 + 2im === @set imag(1) = 2.0
@test 1.0 + 2im === @set imag(1+1im) = 2.0

test_getset_laws(!, true, true, false)
# no need for extensive testing: all invertible lenses are simply forwarded to InverseFunctions
@testset for o in [inv, +, exp, sqrt, @optic(2 + _), @optic(_ * 3), @optic(log(2, _))]
x = 5
test_getset_laws(o, x, 10, 20; cmp=isapprox)
@inferred set(x, o, 10)
end

x = 3 + 4im
@test @set(abs(x) = 10) 6 + 8im
@test @set(angle(x) = π/2) 5im
@test_throws DomainError @set(abs(x) = -10)

# composition
o = @optic 1/(1 + exp(-_))
@test o(2) 0.8807970779778823
@test @inferred(set(2, o, 0.999)) 6.906754778648465
end

@testset "dates" begin
Expand Down

0 comments on commit 2961648

Please sign in to comment.