From 15bb1315d05eeabdca0e47270d2e29249b34d511 Mon Sep 17 00:00:00 2001 From: Alexander Plavin Date: Tue, 10 Dec 2024 12:44:11 -0500 Subject: [PATCH 1/3] show types within optics same as functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For example, show result for @o Tuple(_.a[2]): before: "Tuple ∘ (@o _.a[2])" with this PR: "(@o Tuple(_.a[2]))" --- src/sugar.jl | 2 +- test/test_core.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sugar.jl b/src/sugar.jl index 640636b3..f69764a7 100644 --- a/src/sugar.jl +++ b/src/sugar.jl @@ -493,7 +493,7 @@ IndexLens(::Tuple{Properties}) = Properties() ### nice show() for optics _shortstring(prev, o::PropertyLens{field}) where {field} = "$prev.$field" _shortstring(prev, o::IndexLens) ="$prev[$(join(repr.(o.indices), ", "))]" -_shortstring(prev, o::Function) = _isoperator(o) ? "$o$prev" : "$o($prev)" +_shortstring(prev, o::Union{Function,Type}) = _isoperator(o) ? "$o$prev" : "$o($prev)" _shortstring(prev, o::Base.Fix1) = _isoperator(o.f) ? "$(o.x) $(o.f) $prev" : "$(o.f)($(o.x), $prev)" _shortstring(prev, o::Base.Fix2) = _isoperator(o.f) ? "$prev $(o.f) $(o.x)" : "$(o.f)($prev, $(o.x))" _shortstring(prev, o::Elements) = "$prev[∗]" diff --git a/test/test_core.jl b/test/test_core.jl index 791818f7..3aeeffc5 100644 --- a/test/test_core.jl +++ b/test/test_core.jl @@ -465,6 +465,7 @@ end @test sprint(show, (@optic (_.a + 1) * 2)) == "(@o (_.a + 1) * 2)" @test sprint(show, (@optic (_.a * 2) + 1)) == "(@o (_.a * 2) + 1)" @test sprint(show, (@optic log(_.a[2]))) == "(@o log(_.a[2]))" + @test sprint(show, (@optic Tuple(_.a[2]))) == "(@o Tuple(_.a[2]))" @test sprint(show, (@optic log(_).a[2])) == "(@o _.a[2]) ∘ log" # could be shorter, but difficult to dispatch correctly without piracy @test sprint(show, (@optic log(_.a[2])); context=:compact => true) == "log(_.a[2])" end From a98868d6b95b84371c9f8ac87f79e1d1cf278666 Mon Sep 17 00:00:00 2001 From: Alexander Plavin Date: Wed, 18 Dec 2024 11:35:42 -0500 Subject: [PATCH 2/3] more consistent function/type show Shows unqualified names for both functions (as before) and types. Nice when an optic uses a non-exported type from some module. --- src/sugar.jl | 11 ++++++++--- test/test_core.jl | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/sugar.jl b/src/sugar.jl index f69764a7..a189c03f 100644 --- a/src/sugar.jl +++ b/src/sugar.jl @@ -493,12 +493,17 @@ IndexLens(::Tuple{Properties}) = Properties() ### nice show() for optics _shortstring(prev, o::PropertyLens{field}) where {field} = "$prev.$field" _shortstring(prev, o::IndexLens) ="$prev[$(join(repr.(o.indices), ", "))]" -_shortstring(prev, o::Union{Function,Type}) = _isoperator(o) ? "$o$prev" : "$o($prev)" -_shortstring(prev, o::Base.Fix1) = _isoperator(o.f) ? "$(o.x) $(o.f) $prev" : "$(o.f)($(o.x), $prev)" -_shortstring(prev, o::Base.Fix2) = _isoperator(o.f) ? "$prev $(o.f) $(o.x)" : "$(o.f)($prev, $(o.x))" +_shortstring(prev, o::Union{Function,Type}) = _isoperator(o) ? "$(_fT_repr(o))$prev" : "$(_fT_repr(o))($prev)" +_shortstring(prev, o::Base.Fix1) = _isoperator(o.f) ? "$(o.x) $(_fT_repr(o.f)) $prev" : "$(_fT_repr(o.f))($(o.x), $prev)" +_shortstring(prev, o::Base.Fix2) = _isoperator(o.f) ? "$prev $(_fT_repr(o.f)) $(o.x)" : "$(_fT_repr(o.f))($prev, $(o.x))" _shortstring(prev, o::Elements) = "$prev[∗]" _shortstring(prev, o::Properties) = "$prev[∗ₚ]" +# compact representation of functions and types +# most notably, it deals with the module name in a consistent way: doesn't show it +# by default, it's not shown for functions but shown for types, see https://github.com/JuliaLang/julia/issues/56790 +_fT_repr(o) = repr(o; context=:compact => true) + # can f be stringfied using the operator (infix) syntax? # otherwise uses regular function call syntax _isoperator(f::Function) = Base.isoperator(nameof(f)) diff --git a/test/test_core.jl b/test/test_core.jl index 3aeeffc5..49c09ddb 100644 --- a/test/test_core.jl +++ b/test/test_core.jl @@ -468,6 +468,8 @@ end @test sprint(show, (@optic Tuple(_.a[2]))) == "(@o Tuple(_.a[2]))" @test sprint(show, (@optic log(_).a[2])) == "(@o _.a[2]) ∘ log" # could be shorter, but difficult to dispatch correctly without piracy @test sprint(show, (@optic log(_.a[2])); context=:compact => true) == "log(_.a[2])" + @test sprint(show, (@optic Base.tail(_.a[2])); context=:compact => true) == "tail(_.a[2])" # non-exported function + @test sprint(show, (@optic Base.Fix2(_.a[2])); context=:compact => true) == "Fix2(_.a[2])" # non-exported type end @testset "text/plain show" begin From 1df7bc90c7a9ddb8a4caf3e2acbcd5d0fe6ea9c2 Mon Sep 17 00:00:00 2001 From: Alexander Plavin Date: Sun, 22 Dec 2024 16:10:27 -0500 Subject: [PATCH 3/3] =?UTF-8?q?don't=20append=20"=20=E2=88=98=20(@o=20=5F)?= =?UTF-8?q?"=20in=20show=5Foptic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit show_optic is not a public API, but convenient to use sometimes before, it appended " ∘ (@o _)" unnecessarily for objects that don't have explicit show_optic handling --- src/sugar.jl | 24 ++++++++++++++---------- test/test_core.jl | 5 +++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/sugar.jl b/src/sugar.jl index a189c03f..d3f9f834 100644 --- a/src/sugar.jl +++ b/src/sugar.jl @@ -521,19 +521,23 @@ function show_optic(io, optic) outer = Iterators.dropwhile(x -> applicable(_shortstring, "", x), opts) if !isempty(outer) show(io, opcompose(outer...)) + end + if !isempty(inner) && !isempty(outer) print(io, " ∘ ") end - shortstr = reduce(inner; init=("_", false)) do (prev, need_parens_prev), o - # if _need_parens is true for this o and the one before, wrap the previous one in parentheses - if need_parens_prev && _need_parens(o) - prev = "($prev)" + if !isempty(inner) + shortstr = reduce(inner; init=("_", false)) do (prev, need_parens_prev), o + # if _need_parens is true for this o and the one before, wrap the previous one in parentheses + if need_parens_prev && _need_parens(o) + prev = "($prev)" + end + _shortstring(prev, o), _need_parens(o) + end |> first + if get(io, :compact, false) + print(io, shortstr) + else + print(io, "(@o ", shortstr, ")") end - _shortstring(prev, o), _need_parens(o) - end |> first - if get(io, :compact, false) - print(io, shortstr) - else - print(io, "(@o ", shortstr, ")") end end diff --git a/test/test_core.jl b/test/test_core.jl index 49c09ddb..33f2bfa2 100644 --- a/test/test_core.jl +++ b/test/test_core.jl @@ -470,6 +470,11 @@ end @test sprint(show, (@optic log(_.a[2])); context=:compact => true) == "log(_.a[2])" @test sprint(show, (@optic Base.tail(_.a[2])); context=:compact => true) == "tail(_.a[2])" # non-exported function @test sprint(show, (@optic Base.Fix2(_.a[2])); context=:compact => true) == "Fix2(_.a[2])" # non-exported type + + # show_optic is reasonable even for types without special show_optic handling: + o = Recursive(x->true, Properties()) + @test sprint(Accessors.show_optic, o) == "$o" + @test sprint(Accessors.show_optic, (@o _.a) ∘ o) == "(@o _.a) ∘ $o" end @testset "text/plain show" begin