create_options_manager() creates a runtime configuration manager that supports nested options, group validation, and resetting to defaults. It is ideal for managing complex, interdependent settings in R packages or projects.

create_options_manager(defaults, validators = list())

Arguments

defaults

A named list specifying the default values of the options. Nested lists can be used to represent hierarchical groups of related options.

validators

An optional named list of functions used to validate options. Each function should take a single argument (the value being set) and throw an error if the value is invalid. Names correspond to option paths, e.g., "thermaltime" for a top-level group.

Value

A list with three functions:

get(name = NULL)

Retrieve the current value of an option. Use a dot-separated string for nested options, e.g., "thermaltime.x". If name is NULL, returns all current options.

set(...)

Update one or more options by name. Accepts named arguments in two formats: (1) dot-separated paths like "phenology.thermaltime.y" = ... or (2) nested lists like thermaltime = list(x = ..., y = ...). Both styles can be mixed in a single call. Validators are automatically applied if provided.

reset()

Reset all options to their default values.

Details

This manager allows you to safely store and update related groups of options. For example, a thermaltime group might have x and y vectors that must always have the same length. Using validators ensures that these relationships are maintained whenever options are updated.

The manager supports merge-aware updates, meaning that if a nested list is provided, only the specified elements are updated while others are preserved.

Dot-separated path notation: The set() function now accepts path strings like "phenology.thermaltime.y" = c(0, 25, 0), which are automatically converted to nested lists internally. This provides a more concise syntax for updating deeply nested options without reconstructing the entire hierarchy.

Transactional updates: If validation fails during a set() call, all changes are rolled back and the options remain in their previous state. This ensures that the options manager is always in a consistent state.

Examples

# Define a validator for a group
thermaltime_validator <- function(value) {
    if (!is.list(value) || !all(c("x", "y") %in% names(value))) {
        stop("thermaltime must be a list with both x and y")
    }
    if (length(value$x) != length(value$y)) stop("thermaltime x and y must have same length")
}

# Create a manager
canola <- create_options_manager(
    defaults = list(
        thermaltime = list(x = c(2, 30, 35), y = c(0, 28, 0)),
        frost_threshold = 0
    ),
    validators = list(
        "thermaltime" = thermaltime_validator
    )
)

# Access and update (both methods work)
canola$get("thermaltime.x")
#> [1]  2 30 35

# Method 1: Use dot-separated path strings (concise!)
canola$set("thermaltime.y" = c(0, 25, 0))
canola$set("thermaltime.x" = c(5, 25, 40))

# Method 2: Use nested list (traditional way)
canola$set(thermaltime = list(x = c(5, 25, 40), y = c(0, 20, 0)))

# Method 3: Mix both styles in one call
canola$set(
  "thermaltime.x" = c(10, 30, 45),
  frost_threshold = -2
)

# Reset to defaults
canola$reset()