원클릭으로
miniextendr-dots
Use when the user asks about handling R's ... (dots/variadic) arguments in Rust, the Dots type, the typed_list! macro,
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when the user asks about handling R's ... (dots/variadic) arguments in Rust, the Dots type, the typed_list! macro,
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use when the user asks how to expose a Rust struct as an R class, which R class system to use (R6 vs S3 vs S4 vs S7 vs Env vs Vctrs), how method dispatch works, how constructors are generated, how trait methods map to R, or when working in miniextendr-macros/src/miniextendr_impl/*.rs or miniextendr-macros/src/r_class_formatter.rs.
Use when the user asks about converting between R and Rust types, how TryFromSexp or IntoR work, what NA handling looks like, how strict mode differs from normal coercion, why Vec<i32> from an empty R vector panics, or how bool, Option<T>, or large integer types behave across the R-Rust boundary.
Use when the user asks about ExternalPtr, how Rust structs are stored as R objects, TypedExternal, Box<Box<dyn Any>> storage, pointer provenance for cached_ptr, the release_any finalizer, sidecar field accessors, the TYPE_NAME_CSTR vs TYPE_ID_CSTR distinction, or how to pass an ExternalPtr across crate or package boundaries.
Use when a new user asks how to start a miniextendr-backed R package from zero, how to scaffold via minirextendr::use_miniextendr(), what their first Rust function should look like, what the dev loop is, or "can I add Rust to an existing R package". Also use when someone is confused about which package is which (miniextendr vs minirextendr).
Use when the user asks how
Use when debugging configure.ac failures, Makevars issues, Cargo.lock mismatches, vendor tarball problems, build mode confusion, or the cdylib-to-staticlib double-link pipeline. Also use when changing a Makevars value, diagnosing a latch-leak, understanding the bash-vs-sh configure requirement, or working with m4 quoting in configure.ac.
| name | miniextendr-dots |
| description | Use when the user asks about handling R's ... (dots/variadic) arguments in Rust, the Dots type, the typed_list! macro, |
typed_list!R's ... (dots) passes an untyped sequence of named or unnamed arguments through a call stack. miniextendr maps ... to a &Dots parameter in Rust and provides the typed_list! macro for compile-time-specified runtime validation.
... in my Rust function?"Dots type?"typed_list!?"name @ ... syntax?"#[miniextendr(dots = typed_list!(...))] do?"Dots typeWhen a #[miniextendr] function has ... in its Rust signature, the macro transforms that position into a _dots: &Dots parameter. _dots is the default name; the underscore prefix suppresses unused-variable warnings if you do not use the dots in the function body.
Dots provides three accessors:
| Method | Returns | Description |
|---|---|---|
as_list() | List | Fast unchecked conversion to a List |
try_list() | Result<List, …> | Validated conversion |
typed(spec) | Result<TypedList, TypedListError> | Validate against a TypedListSpec |
name @ ...To give the dots parameter a descriptive name instead of _dots, use the name @ ... syntax:
#[miniextendr]
pub fn my_func(args @ ...) -> i32 {
args.as_list().len() as i32
}
The @ annotation is parsed by the #[miniextendr] macro. The generated R wrapper still uses ...; the Rust binding name is local only.
typed_list! macrotyped_list! creates a TypedListSpec describing the structure expected in dots. Validation happens at R call time.
Syntax:
typed_list!(
field_name => type_spec,
optional_field? => type_spec, // ? marks optional
)
Type specifiers:
| Syntax | Matches |
|---|---|
numeric() | Real/double vector, any length |
numeric(4) | Real/double vector, exactly 4 elements |
integer() | Integer vector |
logical() | Logical vector |
character() | Character vector |
raw() | Raw vector |
complex() | Complex vector |
list() | List (VECSXP or pairlist) |
"data.frame" | Object with that class |
"my_class" | Any class name as a string literal |
By default, extra fields in dots are allowed. Use @exact; at the start of the spec for strict mode:
typed_list!(@exact;
x => numeric(),
y => numeric()
)
The most ergonomic pattern is #[miniextendr(dots = typed_list!(...))]. The macro injects validation at the top of the function body and binds the result to dots_typed:
#[miniextendr(dots = typed_list!(x => numeric(), y => numeric()))]
pub fn compute(...) -> f64 {
let x: Vec<f64> = dots_typed.get("x").expect("x");
let y: Vec<f64> = dots_typed.get("y").expect("y");
x.iter().zip(y.iter()).map(|(a, b)| a + b).sum()
}
The macro expands this to:
let dots_typed = _dots.typed(typed_list!(x => numeric(), y => numeric()))
.expect("dots validation failed");
TypedList accessorsAfter validation, dots_typed (a TypedList) provides:
| Method | Returns |
|---|---|
get::<T>(name) | Result<T, TypedListError> — required field |
get_opt::<T>(name) | Result<Option<T>, TypedListError> — optional field |
get_raw(name) | Result<SEXP, TypedListError> — raw SEXP |
as_list() | List — underlying list |
get::<T>() / get_opt::<T>() accept both scalar and vector target types:
T may be a scalar (f64, i32, String, bool) or a vector/collection
(Vec<f64>, Vec<i32>, Vec<String>, …) — any TryFromSexp with a Display
error type. So let x: Vec<f64> = dots_typed.get("x")? (above) compiles for a
numeric() field, and dots_typed.get::<Vec<i32>>("survive") for an
integer() field.
TypedListError variants emitted on validation failure:
| Variant | Cause |
|---|---|
NotList | Input was not a list |
Missing { name } | Required field absent |
WrongType { name, expected, actual } | Field type mismatch |
WrongLen { name, expected, actual } | Field length mismatch |
ExtraFields { names } | Extra fields in strict (@exact) mode |
DuplicateNames { name } | Duplicate field names |
When #[miniextendr] sees ... in the Rust signature, the generated R wrapper function includes ... in its formals. The .Call invocation collects dots into a named list and passes it as the dots argument to the C wrapper. TryFromSexp converts the incoming pairlist to the Dots type.
Call .typed() directly in the function body instead of using the attribute sugar:
use miniextendr_api::typed_list;
#[miniextendr]
pub fn configure_model(...) -> String {
let spec = typed_list!(
learning_rate => numeric(),
epochs => integer(),
verbose? => logical()
);
let args = match _dots.typed(spec) {
Ok(a) => a,
Err(e) => panic!("{e}"),
};
let lr: f64 = args.get("learning_rate").expect("learning_rate");
format!("lr={lr}")
}
_dots.as_list() (unchecked) or _dots.try_list() (validated).typed_list! either as attribute sugar or manually.?: field? => type_spec.get_opt in the function body._dots?_dots is fine for most functions. The underscore suppresses unused warnings.name @ ... when the name has semantic meaning in the function body (e.g., options @ ...) or you are forwarding to a helper that expects a specific variable name.docs/DOTS_TYPED_LIST.md — full documentation with examples.miniextendr-api/src/dots.rs — Dots type, TypedList, TypedListSpec, TypedListError.miniextendr-macros/src/typed_list.rs — typed_list! macro implementation.match.arg returning the full vector: match.arg(arg = default_choices_vector, several.ok = TRUE) returns the entire choices vector when called with a default multi-element argument. If you use match.arg in an R wrapper alongside dots, check that the defaults are not inadvertently the full choices list. This is a broader match.arg gotcha documented in miniextendr-macros.
Using as_list() when you need validation: as_list() is unchecked. If R calls the function with the wrong types, you get a runtime error deep inside your Rust code instead of a clean validation error. Prefer typed_list! when the schema is known at compile time.
Strict mode rejecting intended extras: @exact causes any unnamed or extra fields to be rejected. If you want to accept caller-defined extras and only validate required fields, omit @exact.
get vs get_opt mismatch: calling get for a field marked ? (optional) panics if the field is absent. Use get_opt for optional fields; it returns None when the field is missing rather than an error.
Duplicate field names in the R call: DuplicateNames fires if the R caller passes the same name twice in .... This is usually an R-side mistake; the error message includes the duplicated name.
miniextendr-macros — broader #[miniextendr] attribute parsing, codegen, match.arg integration.miniextendr-conversions — TryFromSexp and IntoR for field types used inside TypedList::get.