pub struct Quosure<'a> {
quo: SEXP,
expr: SEXP,
env: SEXP,
_arg: PhantomData<&'a SEXP>,
_not_send: PhantomData<*const ()>,
}Expand description
An argument captured as an rlang quosure, rlang::enquo(x): its expression
and environment, with rlang’s argument forwarding and injection resolved.
Take it as a #[miniextendr] parameter. The generated wrapper keeps the
parameter as an R formal and passes
if (missing(x)) quote(expr=) else rlang::enquo(x), which never forces the
argument. Unlike Quoted, a wrapper reached through
function(col) f(data, {{ col }}) or called as f(data, !!sym) receives
the expression the user wrote, in the user’s environment.
The package must list rlang in Imports. The macro cannot see
DESCRIPTION; without rlang the wrapper fails when it is called.
The expression and environment are read from the quosure directly (a
quosure is a one-sided formula, ~expr, of class quosure whose
environment is its .Environment attribute), so Self::expr,
Self::env and Self::as_name call no R code.
Self::eval_tidy evaluates through rlang::eval_tidy(), which resolves
nested quosures and the .data / .env pronouns. Hand Self::sexp to
other quosure-aware R functions (tidyselect::eval_select()) with
RCall::eval_with_handlers.
An argument holding several selections, a role map such as
cols = c(time = TAD, dose = NA), reads entry by entry with
Self::args: each argument of the call as a quosure of its own. A
quosure found in an R object reads with Self::from_sexp, and
Self::new makes one from an expression and an environment.
Fields§
§quo: SEXP§expr: SEXP§env: SEXP§_arg: PhantomData<&'a SEXP>Borrows the root that keeps the quosure alive: the .Call() argument,
the SEXP it was read from, or a ProtectScope.
_not_send: PhantomData<*const ()>R objects stay on R’s main thread.
Implementations§
Source§impl<'a> Quosure<'a>
impl<'a> Quosure<'a>
Sourceunsafe fn read(quo: SEXP) -> Self
unsafe fn read(quo: SEXP) -> Self
Read a quosure’s expression and environment.
§Safety
R’s main thread; quo is a quosure, rooted for 'a.
Source#[doc(hidden)]pub unsafe fn from_wrapper_arg(arg: &'a SEXP) -> Option<Self>
#[doc(hidden)]pub unsafe fn from_wrapper_arg(arg: &'a SEXP) -> Option<Self>
Read the argument a generated wrapper passed for a Quosure parameter:
None when the argument is missing (quote(expr=), or a quosure of
the missing argument, which {{ x }} gives for a missing x).
Generated code calls this; user code has no reason to.
§Panics
When arg is not a quosure.
§Safety
R’s main thread; arg stays rooted for 'a.
Source#[doc(hidden)]pub unsafe fn missing_from_wrapper_arg(arg: &'a SEXP) -> Missing<Self>
#[doc(hidden)]pub unsafe fn missing_from_wrapper_arg(arg: &'a SEXP) -> Missing<Self>
Sourcepub unsafe fn from_sexp(sexp: &'a SEXP) -> Option<Self>
pub unsafe fn from_sexp(sexp: &'a SEXP) -> Option<Self>
Read a quosure the caller holds: None when sexp is not one.
A quosure whose expression is a quosure too, which
rlang::new_quosure(<quosure>) makes, is looked through: the result is
the innermost one, which is what the outer one evaluates to and what
tidyselect::eval_select() accepts (it refuses the outer one). A
quosure of the missing argument is read as it is: Self::expr is
SEXP::missing_arg().
// `call` is the expression of a `Quosure` argument,
// `c(time = {{ t }})` written by a forwarding wrapper.
for (name, arg) in call.args() {
if let Some(quosure) = unsafe { Quosure::from_sexp(&arg) } {
// the quosure `{{ t }}` left in the call, as it is
}
}§Safety
R’s main thread, inside a miniextendr boundary (a #[miniextendr]
body, a with_r_unwind_protect closure; Self::eval_tidy needs
one); sexp stays rooted for 'a.
Sourcepub unsafe fn new(expr: SEXP, env: SEXP, scope: &'a ProtectScope) -> Self
pub unsafe fn new(expr: SEXP, env: SEXP, scope: &'a ProtectScope) -> Self
A quosure of expr in env, rooted by scope.
A bare expression is wrapped with rlang::new_quosure(expr, env). A
quosure is returned as it is, through Self::from_sexp (env is
not used): wrapping a quosure again makes a formula that
tidyselect::eval_select() refuses. So an argument read from a call
can go through new() whether or not a wrapper wrote a quosure there.
The missing argument (an empty argument, c(a = )) is wrapped too:
Self::expr is then SEXP::missing_arg().
Each call protects one value in scope.
§Panics
When env is not an environment, or when expr is not a quosure and
rlang cannot be loaded (a package taking a Quosure lists rlang in
Imports).
§Safety
As Self::from_sexp; expr and env are rooted by the caller for
the call.
Sourcepub fn args<'s>(
&'s self,
scope: &'s ProtectScope,
) -> Option<Vec<(Option<&'s str>, Quosure<'s>)>>
pub fn args<'s>( &'s self, scope: &'s ProtectScope, ) -> Option<Vec<(Option<&'s str>, Quosure<'s>)>>
The arguments of the quosure’s call, each as a quosure with its name,
rooted by scope; None when the expression is not a call.
c(time = TAD, dose = NA) gives (Some("time"), TAD) and
(Some("dose"), NA), each in this quosure’s environment. An argument
a wrapper wrote as a quosure (c(time = {{ t }})) comes back as it is,
in its own environment, as Self::new returns it; any other is
wrapped in this quosure’s environment with rlang::new_quosure(). The
name is None for an unnamed argument; the function (c) is not one
of the arguments.
#[miniextendr]
pub fn roles(data: SEXP, cols: Quosure) -> Vec<String> {
let scope = unsafe { ProtectScope::new() };
let Some(args) = cols.args(&scope) else {
panic!("`cols` must be a call, `c(role = column, ...)`");
};
for (role, quosure) in args {
// `quosure.expr()` is `NA` / `NULL` as written; hand the others
// to `tidyselect::eval_select()`.
}
}All the quosures are held in one list, which scope protects.
§Panics
As Self::new: when an argument is not a quosure and rlang cannot
be loaded.
Sourcepub fn sexp(&self) -> SEXP
pub fn sexp(&self) -> SEXP
The quosure itself, for R functions that take one
(rlang::eval_tidy(), tidyselect::eval_select()).
Sourcepub fn env(&self) -> SEXP
pub fn env(&self) -> SEXP
The quosure’s environment (rlang::quo_get_env()): the empty
environment for a constant.
Sourcepub fn as_name(&self) -> Option<&'a str>
pub fn as_name(&self) -> Option<&'a str>
The name the argument stands for: TIME, "TIME", {{ col }} with
col = TIME and !!rlang::sym("TIME") all give "TIME". A quosure
nested in the expression is looked through. None for any other
expression.
Sourcepub fn eval_tidy(&self, data: SEXP) -> SEXP
pub fn eval_tidy(&self, data: SEXP) -> SEXP
Evaluate the quosure with data as a data mask,
rlang::eval_tidy(quo, data): columns of data win over variables of
the same name in the quosure’s environment, and .data$x / .env$x
pick one side. data may be NULL.
Evaluated with
eval_with_handlers, so the
caller’s handlers see what the expression signals.
The value is unprotected: protect it before the next allocation.
Sourcepub fn try_eval_tidy(&self, data: SEXP) -> Result<SEXP, REvalError>
pub fn try_eval_tidy(&self, data: SEXP) -> Result<SEXP, REvalError>
eval_tidy with an R error returned as Err, as
try_eval_with_handlers
returns it: the caller’s handlers still see the quosure’s warnings and
messages. A missing rlang is an Err too.
The value is unprotected: protect it before the next allocation.
Auto Trait Implementations§
impl<'a> !Send for Quosure<'a>
impl<'a> !Sync for Quosure<'a>
impl<'a> Freeze for Quosure<'a>
impl<'a> RefUnwindSafe for Quosure<'a>
impl<'a> Unpin for Quosure<'a>
impl<'a> UnsafeUnpin for Quosure<'a>
impl<'a> UnwindSafe for Quosure<'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> 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: 24 bytes