Skip to main content

LazyDots

Struct LazyDots 

Source
pub struct LazyDots<'a> {
    env: SEXP,
    len: Cell<Option<usize>>,
    exprs: OnceCell<Exprs>,
    _arg: PhantomData<&'a SEXP>,
    _not_send: PhantomData<*const ()>,
}
Expand description

R’s ..., passed unforced: the generated wrapper’s own frame, whose ... binding holds the dots as R matched them.

Take it as a #[miniextendr] parameter, at the position of ...: fn f(x: SEXP, rest: LazyDots) becomes f <- function(x, ...), and the wrapper passes environment() where a &Dots parameter’s passes list(...). See the module docs.

ⓘ
use miniextendr_api::{LazyDots, SEXP, miniextendr};

/// `update()` with a step per named argument; an empty `select = ` runs the
/// step without its argument.
#[miniextendr(s3(generic = "update", class = "my_obj"))]
pub fn my_obj_update(object: SEXP, rest: LazyDots) -> SEXP {
    for (i, name) in rest.names().into_iter().enumerate() {
        let arg = if rest.is_missing_arg(i) { None } else { Some(rest.force(i)) };
        // ... run step `name` with `arg`
    }
    object
}

Fields§

§env: SEXP

The generated wrapper’s frame (environment()).

§len: Cell<Option<usize>>

...length(), read once.

§exprs: OnceCell<Exprs>

substitute(list(...)), read once.

§_arg: PhantomData<&'a SEXP>

Borrows the .Call() argument that roots the frame.

§_not_send: PhantomData<*const ()>

R objects stay on R’s main thread.

Implementations§

Source§

impl<'a> LazyDots<'a>

Source

#[doc(hidden)]
pub unsafe fn from_wrapper_arg(arg: &'a SEXP) -> Self

Read the argument a generated wrapper passed for a LazyDots parameter: its own frame. Generated code calls this; user code has no reason to.

§Panics

When arg is not an environment.

§Safety

R’s main thread; arg is the frame of a function with a ... formal and stays rooted for 'a.

Source

pub fn len(&self) -> usize

The number of elements in ... (...length()). Empty elements count. Forces nothing.

Source

pub fn is_empty(&self) -> bool

Whether ... holds no elements (...length() == 0).

Source

pub fn names(&self) -> Vec<Option<&'a str>>

The name of each element, as written (...names()): None for an unnamed one, every entry None when nothing is named. A repeated name is kept (f(a = 1, a = 2) gives a, a). Forces nothing.

The names are the print names of the argument tags, which R keeps for the session.

Source

pub fn is_missing_arg(&self, i: usize) -> bool

Whether element i is empty: the slot of f(a = ) or of the fourth position of x[1, , , ], which R stores as the missing argument. Forces nothing.

Only a literally empty slot counts. An element forwarded from a missing argument (g <- function(a) f(1, a) called as g()) is the promise of a, so this is false; forcing it raises argument "a" is missing, with no default.

The first call reads substitute(list(...)) in the frame; the value keeps it, so a loop over the elements reads it once.

§Panics

When i >= self.len().

Source

pub fn expr(&self, i: usize) -> SEXP

The expression element i was written as, as substitute(list(...)) gives it: a promise’s expression (for a forwarded element, what the caller of the forwarding function wrote), a constant as it is, and the empty symbol (quote(expr = )) for an empty element. Forces nothing.

The expression is rooted by this value: it stays valid until the LazyDots drops. The first call reads substitute(list(...)) in the frame; later calls reuse it.

§Panics

When i >= self.len().

Source

pub fn force(&self, i: usize) -> SEXP

Force element i and return its value, as ..k (k = i + 1) gives it in the frame: a promise is forced in its own environment, and a constant comes back as it is.

Evaluated with eval_with_handlers: the caller’s handlers see what forcing signals, and an R error unwinds as the original condition. An empty element raises argument "..k" is missing, with no default; check Self::is_missing_arg first to accept one.

R caches a promise’s value, so forcing an element again returns the stored value without evaluating anything. The value is reachable from the frame (the promise, or the ... binding itself) until the call returns.

§Panics

When i >= self.len(), before anything is forced.

Source

pub fn try_force(&self, i: usize) -> Result<SEXP, REvalError>

Self::force, but an R error raised while forcing comes back as Err(REvalError) instead of unwinding.

Evaluated with try_eval_with_handlers: warnings and messages still reach the caller’s handlers, and any other exit (a tryCatch() handler’s, a restart) unwinds as under Self::force. An empty element is an Err with R’s argument "..k" is missing, with no default.

§Panics

When i >= self.len(), before anything is forced.

Source

pub fn forward(&self, call: RCall) -> SEXP

Evaluate call in the generated wrapper’s frame with the dots passed on: f(<args>, ...), so the callee gets each element as the promise R matched, unevaluated, with the environment it was written in. ... goes last unless RCall::dots put it elsewhere. Nothing is forced here; the callee forces what it reads, or evaluates the expressions against its own data (a data-masking function).

Evaluated with eval_with_handlers, as f(x, ...) in the wrapper would be: the caller’s handlers see the callee’s conditions, and an R error unwinds through the Rust frames as the callee raised it.

Arguments added with RCall::arg_value / RCall::named_value are values. A symbol or call added with RCall::arg is evaluated in the frame, where the wrapper’s formals are bound, so pass a language object with RCall::quoted_arg. A function named by a symbol (RCall::new) is looked up from the frame, as code in the wrapper would look it up: the package’s namespace, its imports, then base and the search path. Name a function from a package that is only suggested with RCall::namespaced.

The value is unprotected.

Source

pub fn try_forward(&self, call: RCall) -> Result<SEXP, REvalError>

Self::forward, but an R error raised by the call comes back as Err(REvalError) instead of unwinding.

Evaluated with try_eval_with_handlers: warnings and messages still reach the caller’s handlers, and any other exit (a tryCatch() handler’s, a restart) unwinds as under Self::forward.

Source

pub fn next_method(&self) -> SEXP

Call the next S3 method: NextMethod(), evaluated in the generated wrapper’s frame. The frame is the S3 method’s own, so R finds the dispatch it is in (.Generic, .Class) and calls the next method with the method’s arguments as R matched them, the dots passed on unevaluated.

Only an S3 method has a dispatch to continue: an s3(...) function or an S3 (or vctrs) impl-block method. Anywhere else R raises its own NextMethod error (“generic function not specified”). Conditions behave as under Self::forward. The value is unprotected.

Source

fn check_index(&self, i: usize)

Panic on an index past the end, as slice indexing does.

Source

fn exprs(&self) -> &Exprs

substitute(list(...)) in the frame, read on first use and rooted until the value drops.

Source

unsafe fn call_in_frame(&self, fun: &CStr, arg: Option<SEXP>) -> SEXP

Evaluate fun() or fun(arg) in the frame, fun the base function of that name. The call’s head is the function itself, looked up in the base environment, so no formal or variable named like it can shadow it; arg is passed as written (the functions used here either take no argument or don’t evaluate it).

§Safety

R’s main thread, inside the #[miniextendr] call; arg is rooted. The result is unprotected.

Trait Implementations§

Source§

impl Debug for LazyDots<'_>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> !Freeze for LazyDots<'a>

§

impl<'a> !RefUnwindSafe for LazyDots<'a>

§

impl<'a> !Send for LazyDots<'a>

§

impl<'a> !Sync for LazyDots<'a>

§

impl<'a> Unpin for LazyDots<'a>

§

impl<'a> UnsafeUnpin for LazyDots<'a>

§

impl<'a> UnwindSafe for LazyDots<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> RDebug for T
where T: Debug,

Source§

fn debug_str(&self) -> String

Get a compact debug string representation.
Source§

fn debug_str_pretty(&self) -> String

Get a pretty-printed debug string with indentation.
Source§

#[doc(hidden)]
unsafe extern "C" fn __RDebug_debug_str_shim( data: *mut c_void, argc: i32, argv: *const SEXP, ) -> SEXP
where Self: Sized + RDebug,

Method shim for RDebug::debug_str. Read more
Source§

#[doc(hidden)]
unsafe extern "C" fn __RDebug_debug_str_pretty_shim( data: *mut c_void, argc: i32, argv: *const SEXP, ) -> SEXP
where Self: Sized + RDebug,

Method shim for RDebug::debug_str_pretty. Read more
Source§

impl<T> SizeHint for T
where T: ?Sized,

Source§

default fn lower_bound(&self) -> usize

🔬This is a nightly-only experimental API. (core_io_internals)
Returns a lower bound on the number of elements this container-like item contains. For example, an array [u8; 12] could return any value between 0 and 12 inclusively as a correct implementation. Read more
Source§

default fn upper_bound(&self) -> Option<usize>

🔬This is a nightly-only experimental API. (core_io_internals)
Returns an upper bound on the number of elements this container-like item contains if it can be determined, otherwise None. Read more
Source§

final fn size_hint(&self) -> (usize, Option<usize>)

🔬This is a nightly-only experimental API. (core_io_internals)
Returns an estimate for the number of elements this container like type contains. Read more
Source§

impl<T> SizedTypeProperties for T

Source§

#[doc(hidden)]
const SIZE: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGNMENT: Alignment = _

🔬This is a nightly-only experimental API. (ptr_alignment_type)
Source§

#[doc(hidden)]
const IS_ZST: bool = _

🔬This is a nightly-only experimental API. (sized_type_properties)
true if this type requires no storage. false if its size is greater than zero. Read more
Source§

#[doc(hidden)]
const LAYOUT: Layout = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const MAX_SLICE_LEN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
The largest safe length for a [Self]. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.

Layout§

Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.

Size: 56 bytes