From d93bc725bcdf943d8e044cfd8b3b08c51382b65f Mon Sep 17 00:00:00 2001 From: Penelope Yong Date: Sat, 4 Apr 2026 21:02:44 +0100 Subject: [PATCH 1/6] Micro-optimise `append_optic` --- HISTORY.md | 4 ++++ Project.toml | 2 +- src/varname/varname.jl | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index dda54cc..404e99c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,7 @@ +## 0.14.2 + +Minor performance optimisation for `AbstractPPL.append_optic`. + ## 0.14.1 Export the `concretize_top_level` function, which concretizes only the indices contained in an `AbstractPPL.Index`, and does not recurse into child optics. diff --git a/Project.toml b/Project.toml index 0fce303..00e48d0 100644 --- a/Project.toml +++ b/Project.toml @@ -3,7 +3,7 @@ uuid = "7a57a42e-76ec-4ea3-a279-07e840d6d9cf" keywords = ["probablistic programming"] license = "MIT" desc = "Common interfaces for probabilistic programming" -version = "0.14.1" +version = "0.14.2" [deps] AbstractMCMC = "80f14c24-f653-4e6a-9b94-39d6b0f70001" diff --git a/src/varname/varname.jl b/src/varname/varname.jl index aa91843..221fa83 100644 --- a/src/varname/varname.jl +++ b/src/varname/varname.jl @@ -400,3 +400,4 @@ x.a.b[1] function append_optic(vn::VarName{sym}, optic::AbstractOptic) where {sym} return VarName{sym}(cat(getoptic(vn), optic)) end +append_optic(vn::VarName, ::Iden) = vn From 7e84ff92b353eb41099a860d6772cdc2ada58653 Mon Sep 17 00:00:00 2001 From: Penelope Yong Date: Sat, 4 Apr 2026 21:03:17 +0100 Subject: [PATCH 2/6] Add tests --- test/varname/varname.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/varname/varname.jl b/test/varname/varname.jl index 660f83c..bf1a372 100644 --- a/test/varname/varname.jl +++ b/test/varname/varname.jl @@ -226,6 +226,8 @@ using JET: @test_call @test append_optic(@varname(x), @opticof(_[1])) == @varname(x[1]) @test append_optic(@varname(x.a), @opticof(_[1])) == @varname(x.a[1]) @test append_optic(@varname(x[1]), @opticof(_.a)) == @varname(x[1].a) + @test append_optic(@varname(x), @opticof(_)) == @varname(x) + @test append_optic(@varname(x.a), @opticof(_)) == @varname(x.a) end end From 64867401875e1314aaed50156e5879a8ab46c458 Mon Sep 17 00:00:00 2001 From: Penelope Yong Date: Sat, 4 Apr 2026 21:13:54 +0100 Subject: [PATCH 3/6] tweak tests --- test/varname/serialize.jl | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/test/varname/serialize.jl b/test/varname/serialize.jl index 265de0e..5a97dac 100644 --- a/test/varname/serialize.jl +++ b/test/varname/serialize.jl @@ -41,19 +41,11 @@ using Test @varname(x[j=2, i=1]), @varname(x[i=1, j=2]), @varname(x[].a[j=2].b[3, 4, 5, [6]]), + @varname(x[[1, 2, 5, 6]]), ] for vn in vns @test string_to_varname(varname_to_string(vn)) == vn end - - # For this VarName, the {de,}serialisation works correctly but we must - # test in a different way because equality comparison of structs with - # vector fields (such as Accessors.IndexLens) compares the memory - # addresses rather than the contents (thus vn_vec == vn_vec2 returns - # false). - vn_vec = @varname(x[[1, 2, 5, 6]]) - vn_vec2 = string_to_varname(varname_to_string(vn_vec)) - @test hash(vn_vec) == hash(vn_vec2) end @testset "deserialisation fails for unconcretised dynamic indices" begin From 1a88ae011926d8abd09f1e17a48662a01f155192 Mon Sep 17 00:00:00 2001 From: Penelope Yong Date: Sat, 4 Apr 2026 21:18:02 +0100 Subject: [PATCH 4/6] bump workflow versions --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index cb5be58..3a992da 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -31,13 +31,13 @@ jobs: os: macos-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.runner.version }} - - uses: julia-actions/cache@v2 + - uses: julia-actions/cache@v3 - uses: julia-actions/julia-buildpkg@v1 From 9833ca74771da91472e1fb59fa96267e0cf5df49 Mon Sep 17 00:00:00 2001 From: Penelope Yong Date: Sat, 4 Apr 2026 21:50:00 +0100 Subject: [PATCH 5/6] Change OrderedDict -> NamedTuple https://github.com/JuliaIO/JSON.jl/issues/447 --- src/varname/serialize.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/varname/serialize.jl b/src/varname/serialize.jl index 6064e81..0579c43 100644 --- a/src/varname/serialize.jl +++ b/src/varname/serialize.jl @@ -124,7 +124,7 @@ function optic_to_dict(i::Index) # For some reason if you don't do the isempty check, it gets serialised as `{}` # rather than `[]` "ix" => isempty(i.ix) ? [] : collect(map(index_to_dict, i.ix)), - "kw" => OrderedDict(String(x) => index_to_dict(y) for (x, y) in pairs(i.kw)), + "kw" => NamedTuple{keys(i.kw)}(map(index_to_dict, values(i.kw))), "child" => optic_to_dict(i.child), ) end From 021196608d989712241a47ce298890d90f6b0afa Mon Sep 17 00:00:00 2001 From: Penelope Yong Date: Sat, 4 Apr 2026 21:57:28 +0100 Subject: [PATCH 6/6] Add changelog note --- HISTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 404e99c..8d8e0e4 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,7 @@ ## 0.14.2 +Fix string serialisation of VarNames such that the order of keyword arguments is preserved (this was previously guaranteed, but JSON.jl v1.5.0 introduced a change that caused the keyword arguments to always be sorted.) + Minor performance optimisation for `AbstractPPL.append_optic`. ## 0.14.1