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: SEXPThe 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>
impl<'a> LazyDots<'a>
Source#[doc(hidden)]pub unsafe fn from_wrapper_arg(arg: &'a SEXP) -> Self
#[doc(hidden)]pub unsafe fn from_wrapper_arg(arg: &'a SEXP) -> Self
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
The number of elements in ... (...length()). Empty elements count.
Forces nothing.
Sourcepub fn names(&self) -> Vec<Option<&'a str>>
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.
Sourcepub fn is_missing_arg(&self, i: usize) -> bool
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().
Sourcepub fn expr(&self, i: usize) -> SEXP
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().
Sourcepub fn force(&self, i: usize) -> SEXP
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.
Sourcepub fn try_force(&self, i: usize) -> Result<SEXP, REvalError>
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.
Sourcepub fn forward(&self, call: RCall) -> SEXP
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.
Sourcepub fn try_forward(&self, call: RCall) -> Result<SEXP, REvalError>
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.
Sourcepub fn next_method(&self) -> SEXP
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.
Sourcefn check_index(&self, i: usize)
fn check_index(&self, i: usize)
Panic on an index past the end, as slice indexing does.
Sourcefn exprs(&self) -> &Exprs
fn exprs(&self) -> &Exprs
substitute(list(...)) in the frame, read on first use and rooted
until the value drops.
Sourceunsafe fn call_in_frame(&self, fun: &CStr, arg: Option<SEXP>) -> SEXP
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§
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> RDebug for Twhere
T: Debug,
impl<T> RDebug for Twhere
T: Debug,
Source§impl<T> SizeHint for Twhere
T: ?Sized,
impl<T> SizeHint for Twhere
T: ?Sized,
Source§default fn lower_bound(&self) -> usize
default fn lower_bound(&self) -> usize
core_io_internals)[u8; 12] could return any value between 0 and
12 inclusively as a correct implementation. Read moreSource§impl<T> SizedTypeProperties for T
impl<T> SizedTypeProperties for T
Source§#[doc(hidden)]const SIZE: usize = _
#[doc(hidden)]const SIZE: usize = _
sized_type_properties)Source§#[doc(hidden)]const ALIGN: usize = _
#[doc(hidden)]const ALIGN: usize = _
sized_type_properties)Source§#[doc(hidden)]const ALIGNMENT: Alignment = _
#[doc(hidden)]const ALIGNMENT: Alignment = _
ptr_alignment_type)Source§#[doc(hidden)]const IS_ZST: bool = _
#[doc(hidden)]const IS_ZST: bool = _
sized_type_properties)Source§#[doc(hidden)]const LAYOUT: Layout = _
#[doc(hidden)]const LAYOUT: Layout = _
sized_type_properties)Source§#[doc(hidden)]const MAX_SLICE_LEN: usize = _
#[doc(hidden)]const MAX_SLICE_LEN: usize = _
sized_type_properties)[Self]. Read moreLayout§
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