You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add a leaf-name param accessor (getparam) to remove the dotted-key footgun #12
DataKey.params is keyed by the dotted group.leaf path, so a work_fn must
write key.params["system.N"]. The plain leaf key.params["N"] silently raises KeyError. This is the single most common point of confusion when writing a work_fn (and a frequent mistake for code-generating assistants): the dotted
form is implicit — it comes from the [paramsets.system] table nesting, not
from anything the user typed literally — so the natural guess params["N"] is
wrong with no hint as to why.
Proposed enhancement
Add a core accessor that resolves an unambiguous leaf name and reuses the
existing AmbiguousPathKeyError machinery, so the dotted form keeps working
unchanged but the leaf form is also supported and fails loudly:
""" getparam(key::DataKey, pk) -> valueLook up `pk` in `key.params`, accepting either an exact key ("system.N" or atop-level "N") or an unambiguous leaf name ("N" matching "system.N").Throws AmbiguousPathKeyError if the leaf appears in multiple groups."""functiongetparam(key::DataKey, pk::AbstractString)
haskey(key.params, pk) &&return key.params[pk]
matches = [(k, v) for (k, v) in key.params if_split_dotted(k)[2] == pk]
isempty(matches) &&throw(KeyError(pk))
length(matches) >1&&throw(AmbiguousPathKeyError(String(pk),
sort([_split_dotted(m[1])[1] for m in matches])))
return matches[1][2]
end
getparam(key, "N") then works whether the config wrote system.N or a
top-level N, and on a genuine collision (system.Nandmodel.N) it raises
the same actionable error format_path/resolve_path_keys already use, instead
of a silent KeyError.
Use case
Every work_fn in apps/ReducedEnvExperiments.jl indexes params["system.N"], params["system.chi"], params["strategy.name"], … A leaf accessor removes the
need to memorize the group prefix and converts the most common silent failure
into either a correct lookup or an explicit, fixable error. (Mirrors the
leaf-resolution format_path already does internally.)
Already implemented, as param rather than getparam (#33, closing #32, merged 2026-09-08).
src/core/param.jl + src/util/resolve.jl give exactly the resolution rule proposed here: exact match on the dotted name, else a unique match on the leaf, and AmbiguousPathKeyError naming the groups when the leaf sits in more than one.
param(key, "system.N") # exactparam(key, "N") # leaf, when unambiguousparam(key, "N") # AmbiguousPathKeyError("N", ["model", "system"]) when not
Two things the shipped version has that this proposal did not:
param(key, name, T) converts and then, for numbers, checks the value survived the conversion; convert alone silently rounds Float32 from 2.1. That covers the other half of the Float64(key.params["system.kbT"]) idiom this issue was about.
the rule lives in one place (_resolve_name) with _lookup_name underneath it, so a caller that treats absent and ambiguous as ordinary outcomes does not reach them through a catch.
Activity
sotashimozono commentedon Sep 15, 2026
Already implemented, as
paramrather thangetparam(#33, closing #32, merged 2026-09-08).src/core/param.jl+src/util/resolve.jlgive exactly the resolution rule proposed here: exact match on the dotted name, else a unique match on the leaf, andAmbiguousPathKeyErrornaming the groups when the leaf sits in more than one.Two things the shipped version has that this proposal did not:
param(key, name, T)converts and then, for numbers, checks the value survived the conversion;convertalone silently roundsFloat32from2.1. That covers the other half of theFloat64(key.params["system.kbT"])idiom this issue was about._resolve_name) with_lookup_nameunderneath it, so a caller that treats absent and ambiguous as ordinary outcomes does not reach them through acatch.Closing as implemented.