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
cmdstan_model(compile = FALSE) and the $compile() method both go. Options become one-shot: cmdstan_model() is the only place a build is configured, and every call states what it wants.
Current usage to migrate: 96 compile = FALSE in tests, 10 in R/, 9 in man/, 5 in vignettes.
Why removing $compile() rather than narrowing it
Once deferred compilation is gone it has no unique purpose — cmdstan_model(file, force_recompile = TRUE, ...) covers every remaining use. A $compile() that instead rebuilt "as recorded" would have to replay build arguments from a file, which needs a strictly validated record schema before it could be safe.
Nothing structural blocks removal: fits do not hold model references (R/fit.R:20-26 copies the model-methods environment rather than pointing at the object).
This must ship together with #1255. If $compile() is removed before configuration mismatches trigger rebuilds, an existing unthreaded executable is still reused under today's logic while the only escape route is gone — which breaks the central promise of the new API in the window between them.
Standalone replacements
The introspection use cases compile = FALSE served are better handled by functions that never needed a model object. Names follow cmdstanpy where a counterpart exists, and cmdstanr's existing write_stan_file():
Every one that hands a source file to stanc takes include_paths (#1254 §8, "Every function that hands a source file to stanc takes include_paths"). For format_stan_file() that is correctness rather than symmetry: $format() reads self$include_paths() internally today (R/model.R:1252), so a standalone with no object to read from cannot format any program containing #include at all.
compile_stan_file() and format_stan_file() match cmdstanpy exactly. model_variables() at R/model.R:2657 is already this shape internally.
compile_stan_file() is exported, sharing one implementation
An earlier version of this issue said to export it only if a consumer committed to it. That was the wrong bar — the argument is parity, not demand: cmdstanpy already has compile_stan_file, and having format_stan_file() and check_syntax_stan_file() public while the compile step is not is arbitrary. With compile = FALSE gone there would otherwise be no way to build without constructing an R6 object.
One implementation, two entry points, so nothing is duplicated:
compile_impl(stan_file, cpp_options, stanc_options, include_paths,
user_header, pedantic, dir, force_recompile, quiet, dry_run)
-> list(path =, record =, src_info =, hpp_code =)
compile_stan_file(...) # exported: compile_impl(...)$path
cmdstan_model(...) # exported: R6 object built from all four
This is a lift of today's $compile() rather than a rewrite — the stanc and make invocation moves unchanged, and 12 of its 31 private$ touches are the precompile_* fields this issue deletes anyway.
The internal returns more than a path, or cmdstan_model() re-reads the record and re-runs stanc. It needs record for $cpp_options(), $user_header() (new, Design note: v1.0 compilation state and C++ options #1254 §3) and $cmdstan_version(), and src_info for the eager $code()/$variables() snapshot — the stanc --info call the build already makes.
dry_run lives on the internal only. The one argument the public wrapper omits.
compile_stan_file() performs the same up-to-date check, reusing a current executable rather than always compiling, and writes the record so a later cmdstan_model(exe_file = path) knows provenance (Record what an executable was built with, alongside the executable? #1238). Worth documenting, since the verb suggests otherwise.
force_recompile keeps cmdstanr's spelling rather than cmdstanpy's force: matching the function name is what buys cross-implementation teachability, matching every argument at the cost of internal consistency is not.
Where cmdstanpy already has a name we copy it; where it does not, we pick one and they can copy it if they add a counterpart (#1254 §8). The two APIs are taught together, so parity matters, but nothing here waits on a joint naming decision.
stan_variables() is the one name to revisit before it ships. metadata()$stan_variables already exists on fit objects (R/csv.R:362) and means the variable names in the output rather than the declarations in the program. That is not a collision in R and not a reason to hold the design; the name is provisional and the decision belongs with the implementation.
Removes precompile_stanc_options_, precompile_include_paths_, precompile_cpp_options_, the %||% include-path baseline and include_paths_dirty_ (R/model.R:642-656).
dry_run demotes to internal. Its documentation says "Used to speedup tests" (R/model.R:558-559); 22 test uses, zero vignette uses. It is what makes migrating the 96 compile = FALSE sites affordable.
$format() gets a standalone plus a method wrapper. It must stop refreshing stan_code_/variables_ (R/model.R:1309-1311) — formatting makes the object stale rather than updating it.
Design note: #1254.
cmdstan_model(compile = FALSE)and the$compile()method both go. Options become one-shot:cmdstan_model()is the only place a build is configured, and every call states what it wants.Current usage to migrate: 96
compile = FALSEin tests, 10 inR/, 9 inman/, 5 in vignettes.Why removing
$compile()rather than narrowing itOnce deferred compilation is gone it has no unique purpose —
cmdstan_model(file, force_recompile = TRUE, ...)covers every remaining use. A$compile()that instead rebuilt "as recorded" would have to replay build arguments from a file, which needs a strictly validated record schema before it could be safe.Nothing structural blocks removal: fits do not hold model references (
R/fit.R:20-26copies the model-methods environment rather than pointing at the object).This must ship together with #1255. If
$compile()is removed before configuration mismatches trigger rebuilds, an existing unthreaded executable is still reused under today's logic while the only escape route is gone — which breaks the central promise of the new API in the window between them.Standalone replacements
The introspection use cases
compile = FALSEserved are better handled by functions that never needed a model object. Names follow cmdstanpy where a counterpart exists, and cmdstanr's existingwrite_stan_file():Every one that hands a source file to stanc takes
include_paths(#1254 §8, "Every function that hands a source file to stanc takesinclude_paths"). Forformat_stan_file()that is correctness rather than symmetry:$format()readsself$include_paths()internally today (R/model.R:1252), so a standalone with no object to read from cannot format any program containing#includeat all.compile_stan_file()andformat_stan_file()match cmdstanpy exactly.model_variables()atR/model.R:2657is already this shape internally.compile_stan_file()is exported, sharing one implementationAn earlier version of this issue said to export it only if a consumer committed to it. That was the wrong bar — the argument is parity, not demand: cmdstanpy already has
compile_stan_file, and havingformat_stan_file()andcheck_syntax_stan_file()public while the compile step is not is arbitrary. Withcompile = FALSEgone there would otherwise be no way to build without constructing an R6 object.One implementation, two entry points, so nothing is duplicated:
This is a lift of today's
$compile()rather than a rewrite — the stanc and make invocation moves unchanged, and 12 of its 31private$touches are theprecompile_*fields this issue deletes anyway.cmdstan_model()re-reads the record and re-runs stanc. It needsrecordfor$cpp_options(),$user_header()(new, Design note: v1.0 compilation state and C++ options #1254 §3) and$cmdstan_version(), andsrc_infofor the eager$code()/$variables()snapshot — thestanc --infocall the build already makes.hpp_codeanswers $expose_functions() reports "pre-compiled Stan model" for a model that was never compiled #1245's discriminator — populated when a build ran, absent when an executable was reused, which is the "is there generated C++?" half of the two questions that issue needs.dry_runlives on the internal only. The one argument the public wrapper omits.compile_stan_file()performs the same up-to-date check, reusing a current executable rather than always compiling, and writes the record so a latercmdstan_model(exe_file = path)knows provenance (Record what an executable was built with, alongside the executable? #1238). Worth documenting, since the verb suggests otherwise.force_recompilekeeps cmdstanr's spelling rather than cmdstanpy'sforce: matching the function name is what buys cross-implementation teachability, matching every argument at the cost of internal consistency is not.Where cmdstanpy already has a name we copy it; where it does not, we pick one and they can copy it if they add a counterpart (#1254 §8). The two APIs are taught together, so parity matters, but nothing here waits on a joint naming decision.
stan_variables()is the one name to revisit before it ships.metadata()$stan_variablesalready exists on fit objects (R/csv.R:362) and means the variable names in the output rather than the declarations in the program. That is not a collision in R and not a reason to hold the design; the name is provisional and the decision belongs with the implementation.Consequences
$check_syntax()and$format()— disappears with the precompile store.precompile_stanc_options_,precompile_include_paths_,precompile_cpp_options_, the%||%include-path baseline andinclude_paths_dirty_(R/model.R:642-656).dry_rundemotes to internal. Its documentation says "Used to speedup tests" (R/model.R:558-559); 22 test uses, zero vignette uses. It is what makes migrating the 96compile = FALSEsites affordable.$format()gets a standalone plus a method wrapper. It must stop refreshingstan_code_/variables_(R/model.R:1309-1311) — formatting makes the object stale rather than updating it.