Skip to main content

typed_list

Macro typed_list 

Source
typed_list!() { /* proc-macro */ }
Expand description

Create a TypedListSpec for validating ... arguments or lists.

This macro provides ergonomic syntax for defining typed list specifications that can be used with Dots::typed() to validate the structure of ... arguments passed from R.

§Syntax

typed_list!(
    name => type_spec,    // required field with type
    name? => type_spec,   // optional field with type
    name,                 // required field, any type
    name?,                // optional field, any type
)

For strict mode (no extra fields allowed):

typed_list!(@exact; name => type_spec, ...)

§Type Specifications

§Base types (with optional length)

  • numeric() / numeric(4) - Real/double vector
  • integer() / integer(4) - Integer vector
  • logical() / logical(4) - Logical vector
  • character() / character(4) - Character vector
  • raw() / raw(4) - Raw vector
  • complex() / complex(4) - Complex vector
  • list() / list(4) - List (VECSXP)

§Special types

  • data_frame() - Data frame
  • factor() - Factor
  • matrix() - Matrix
  • array() - Array
  • function() - Function
  • environment() - Environment
  • null() - NULL only
  • any() - Any type

§String literals

  • "numeric", "integer", etc. - Same as call syntax
  • "data.frame" - Data frame (alias)
  • "MyClass" - Any other string is treated as a class name (uses Rf_inherits)

§Examples

§Basic usage

use miniextendr_api::{miniextendr, typed_list, Dots};

#[miniextendr]
pub fn process_args(dots: ...) -> Result<i32, String> {
    let args = dots.typed(typed_list!(
        alpha => numeric(4),
        beta => list(),
        gamma? => "character",
    )).map_err(|e| e.to_string())?;

    let alpha: Vec<f64> = args.get("alpha").map_err(|e| e.to_string())?;
    Ok(alpha.len() as i32)
}

§Strict mode

// Reject any extra named fields
let args = dots.typed(typed_list!(@exact;
    x => numeric(),
    y => numeric(),
))?;

§Class checking

// Check for specific R class (uses Rf_inherits semantics)
let args = dots.typed(typed_list!(
    data => "data.frame",
    model => "lm",
))?;

§Attribute sugar

Instead of calling .typed() manually, you can use typed_list! directly in the #[miniextendr] attribute for automatic validation:

#[miniextendr(dots = typed_list!(x => numeric(), y => numeric()))]
pub fn my_func(...) -> String {
    // `dots_typed` is automatically created and validated
    let x: f64 = dots_typed.get("x").expect("x");
    let y: f64 = dots_typed.get("y").expect("y");
    format!("x={}, y={}", x, y)
}

This injects validation at the start of the function body:

let dots_typed = _dots.typed(typed_list!(...)).expect("dots validation failed");

See the #[miniextendr] attribute documentation for more details.