Defaults and inheritance
The default
configuration provides a set of values to
use when no named configuration is active. Other configurations
automatically inherit all default
values so need only
define values specialized for that configuration.
For example, in this configuration the production
configuration doesn’t specify a value for trials
so it will
be read from the default
configuration:
config.yml
R
config::get(config = "production")
#> $trials
#> [1] 5
#>
#> $dataset
#> [1] "data.csv"
All configurations automatically inherit from the
default
configuration. Configurations can also inherit from
one or more other named configurations. For example, in this file the
production
configuration inherits from the
test
configuration:
config.yml
default:
trials: 5
dataset: "data-sampled.csv"
test:
trials: 30
dataset: "data-test.csv"
production:
inherits: test
dataset: "data.csv"
R
config::get(config = "production")
#> $trials
#> [1] 30
#>
#> $inherits
#> [1] "test"
#>
#> $dataset
#> [1] "data.csv"
Using R code inside the yaml file
You can execute R code within configuration files by prefacing values
with !expr
. This could be useful in cases where you want to
base configuration values on environment variables, R options, or even
other config files. For example:
config.yml
default:
cores: 2
debug: true
server: "localhost:5555"
production:
cores: !expr getOption("mc.cores")
debug: !expr Sys.getenv("ENABLE_DEBUG") == "1"
server: !expr config::get("server", file = "etc/server-config.yml")
The default result:
R
config::get("server")
#> [1] "localhost:5555"
The production result will depend on the environment variables on the server:
server-config.yml
R
config::get("server", config = "production")
#> [1] "production.example.com"
Referencing previously assigned parameters
You can use any previously assigned parameter inside of R code so long as it is assigned directly.
config.yml
default:
file: "data.csv"
test:
data_dir: "test/out"
dataset: !expr file.path(data_dir, file)
production:
data_dir: "production/out"
dataset: !expr file.path(data_dir, file)
R
config::get("dataset", config = "test")
#> [1] "test/out/data.csv"
R
config::get(config = "production")
#> $file
#> [1] "data.csv"
#>
#> $data_dir
#> [1] "production/out"
#>
#> $dataset
#> [1] "production/out/data.csv"
Limitations of using R expressions
The ability to use R expressions gives substantial flexibility to allow configurations to depend on environment variables, files and other information that’s available in the target environment.
However, keep in mind these limitations:
- Any R expression can only refer to elements in the configuration file that it inherits from.
- An R expression can not refer to another R expression.
If the config file violates these limitations,
config::get()
will throw an error.
As an example, let’s say you want to construct a configuration that computes a location based on a filename and a folder.
A valid example
If both filename
and folder
are constant
(i.e. not computed expressions) this works:
config.yml
R
config::get("location")
#> [1] "some/path/trials.csv"
An invalid example
However, if folder
is also a computed value, then
location
can not be computed and this throws an error:
config.yml
default:
filename: "trials.csv"
folder: !expr c("some/path")
location: !expr file.path(folder, filename)
R
config::get("location")
#> Error in config::get("location"): Attempt to assign nested list value from expression.
#> Only directly assigned values can be used in expressions.
#> Original Error:
#> * eval(expr, envir = envir): object 'folder' not found