Add other_mort() and other_encounter() accessors (#579) - #585
Merged
Conversation
The guide to creating an extension package described mizerStarvation as
adding starvation mortality "via the `other_mort` argument in
`setComponent()`". There is no such argument, and mizerStarvation does not
call `setComponent()` at all -- it assigns into `params@other_mort`
directly. A reader following the sentence hit
Error: argument "dynamics_fun" is missing, with no default
Behind the wrong sentence was a real gap. `@other_mort` and
`@other_encounter` had no exported accessor, so `setComponent()` -- which
requires a `dynamics_fun` and an `initial_value` -- was the only supported
writer, and a term that carries no state of its own had nothing to supply
for either. mizer already had the parallel pair for the fixed-array case,
`ext_mort()` and `ext_encounter()`.
Fill in the two missing cells:
other_mort(params)[["starvation"]] <- "starvMort"
Like `other_params()`, the accessors hide the entries belonging to a
component: those stay the property of `setComponent()`, `getComponent()`
and `removeComponent()`, so assigning a whole list cannot wipe them out.
Getter and setter therefore have the same scope. Validation rejects a name
that is not a function, an unnamed entry, and a name that collides with a
component; assigning NULL removes an entry.
`setComponent()` now also refuses a component name that a free-standing
contribution already holds, instead of silently taking it over and hiding
it from the accessors. That is the one behaviour change, and it is recorded
in the upgrading guide with a row in the symptom index.
Rewrite the guide sentence to describe the supported route, add the
mechanism to the extend-mizer skill and a bullet to the package-author
checklist, and regenerate the articles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gustavdelius
force-pushed
the
other-mort-accessors
branch
from
August 27, 2026 11:36
65ac328 to
fd12746
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #579.
The reported bug
The guide to creating an extension package described mizerStarvation as adding starvation mortality "via the
other_mortargument insetComponent()". There is no such argument (the mortality argument ismort_fun), and mizerStarvation does not callsetComponent()at all — it assignsparams@other_mort[["starvation"]] <- "starvMort"directly. A reader following the guide's simplest worked example hitError: argument "dynamics_fun" is missing, with no default.The gap behind it
@other_mortand@other_encounterare named lists of function names thatgetMort()andgetEncounter()iterate over and add to their results, and they had no exported accessor.other_params()deliberately reaches onlyparams@other_params$other, andsetComponent()was the only exported writer of the two slots — but it requiresdynamics_funandinitial_value, which a term carrying no state of its own has nothing to supply. mizer already half-filled the table:ext_mort()/ext_mort<-()@other_mort— nothingext_encounter()/ext_encounter<-()@other_encounter— nothingThe route mizerStarvation actually takes is also a one-way door:
getComponent()andremoveComponent()are keyed onnames(params@other_dynamics), so a bare@other_mortentry can neither be inspected nor removed through the API.Changes
New accessors (
R/extension.R) —other_mort()/other_encounter()and their replacement forms, as plain functions alongsideother_params():other_params()does and for the same reason. An entry created bysetComponent(mort_fun = )stays the property of its component —getComponent()reports it,removeComponent()removes it — so assigning a whole list through the accessor can no longer wipe it out. Getter and setter have the same scope, soother_mort(params) <- other_mort(params)is an exact identity.setComponent()). AssigningNULLremoves an entry;other_mort(params) <- NULLclears the free-standing ones only.other_dynamicsdeliberately gets no accessor: it is coupled to@initial_n_other(MizerSimvalidity checks the two agree), so it stays behindsetComponent().other_mortandother_encounterare independent registries with nothing to keep in sync.setRateContributions().One behaviour change —
setComponent()now refuses a component name that a free-standing contribution is already registered under, instead of silently taking it over and hiding it from the accessors. Recorded ininst/skills/upgrade-mizer-code/references/mizer-3.4.mdwith a row in the symptom index.Documentation — the wrong sentence in
inst/skills/create-extension-package/SKILL.mdis rewritten to describe the supported route, with the two neighbouring mechanisms (ext_mort()for a fixed array,setComponent(mort_fun = )for a component with state) spelled out so they cannot be confused again; a bullet added to the package-author checklist; a row and a paragraph added toinst/skills/extend-mizer/SKILL.md. The articles were regenerated withbuild_guides()— no generated vignette was edited by hand.Verification
[ FAIL 0 | WARN 0 | SKIP 49 | PASS 4947 ]tests/testthat/test-extension.R: round trip, filtering, preservation across a whole-list assignment, the four validation errors, removal viaNULL, both rates actually rising, projection of a model with a free-standing contribution and no components at all, thesetComponent()collision guard, andtime_modifiedfor both setters.pkgdown::check_pkgdown()clean; the new page is picked up byhas_concept("extension tools")with no_pkgdown.ymledit.lintr::lint()clean on the new lines.build_guides()reports "All links resolve" — which is also what checks that the new symptom-index row resolves to its heading and that its quoted error text is still a literal inR/.inst/llms.txt/docs/llms.txtdo not yet list the new exports; they are regenerated from a full pkgdown site build.🤖 Generated with Claude Code