pub struct EagerRuntime { /* private fields */ }Expand description
Shared eager execution context for tensors on a backend.
Reusing one context lets eager tensors share backend state, extension runtime caches, and gradient storage across a computation.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let x = EagerTensor::from_tensor_in(Tensor::from_vec_col_major(vec![1], vec![1.0_f64]).unwrap(), ctx.clone()).unwrap();
let y = EagerTensor::from_tensor_in(Tensor::from_vec_col_major(vec![1], vec![2.0_f64]).unwrap(), ctx.clone()).unwrap();
let z = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |session| session.add(&x, &y)).unwrap();
assert_eq!(z.value().unwrap().as_slice::<f64>().unwrap(), &[3.0]);Implementations§
Source§impl EagerRuntime
impl EagerRuntime
Sourcepub fn new() -> Result<Arc<Self>>
pub fn new() -> Result<Arc<Self>>
Create a shared eager execution context.
The context stores no engine: every operation runs on the engine the caller passes in.
§Examples
use tenferro_ad::EagerRuntime;
let ctx = EagerRuntime::new()?;
assert_eq!(std::sync::Arc::strong_count(&ctx), 1);§Errors
Returns Error::RuntimeStateSource when the prepared-program runtime
cannot be configured, preserving the underlying RuntimeConfigError.
Sourcepub fn with_ad_context(ad: &AdContext) -> Result<Arc<Self>>
pub fn with_ad_context(ad: &AdContext) -> Result<Arc<Self>>
Create a shared eager execution context that uses the semantic
extension rules and AD transform cache of ad.
§Examples
use tenferro_ad::{AdContext, EagerRuntime};
let ad = AdContext::builder().build().unwrap();
let ctx = EagerRuntime::with_ad_context(&ad)?;
assert_eq!(std::sync::Arc::strong_count(&ctx), 1);§Errors
Returns Error::RuntimeStateSource when the prepared-program runtime
cannot be configured.
Sourcepub fn id(&self) -> ContextId
pub fn id(&self) -> ContextId
Return an opaque identifier for this context.
§Examples
use tenferro_ad::{EagerRuntime};
let ctx = EagerRuntime::new()?;
assert_ne!(ctx.id(), EagerRuntime::new()?.id());Sourcepub fn no_grad(&self) -> EagerNoGradGuard
pub fn no_grad(&self) -> EagerNoGradGuard
Disable eager operation recording on the current thread until the guard is dropped.
This is useful for optimizer updates, metric calculations, and other eager computations that should not become part of the AD tape.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![3.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| {
let _guard = ctx.no_grad();
s.mul(&x, &x)
})?;
assert!(!y.tracks_grad());Sourcepub fn capture_trace(&self) -> EagerTraceCaptureGuard
pub fn capture_trace(&self) -> EagerTraceCaptureGuard
Keep semantic-trace recording active for untracked intermediates.
See EagerTraceCaptureGuard for the full contract and an example.
Sourcepub fn install_extension_module(
&self,
module: Arc<dyn ExtensionModule>,
) -> Result<RuntimeEpoch>
pub fn install_extension_module( &self, module: Arc<dyn ExtensionModule>, ) -> Result<RuntimeEpoch>
Install or replace one extension module on this eager context’s runtime.
Eager extension wrappers call this as an idempotent “ensure installed” step. When the exact module instance (same module ID and allocation) is already installed, this is a read-only no-op that returns the current runtime epoch without acquiring the install lock or reconfiguring. The cold or replacement paths keep the transactional install-or-replace behavior, serialized so parallel first-use of the same extension family cannot publish over another thread’s base snapshot.
§Errors
Returns tenferro_runtime::Error::RuntimeState when runtime
reconfiguration fails or the extension module transaction is invalid.
Sourcepub fn clear_caches(&self) -> Result<()>
pub fn clear_caches(&self) -> Result<()>
Clear every cache owned by this eager context.
§Examples
use tenferro_ad::{EagerRuntime};
let ctx = EagerRuntime::new()?;
ctx.clear_caches()?;
assert_eq!(ctx.cache_stats()?.ad_transforms.entries, 0);
assert_eq!(ctx.cache_stats()?.prepared_derivatives.entries, 0);§Errors
Returns tenferro_runtime::Error::RuntimeState when either the
extension cache or AD-transform cache is poisoned.
Sourcepub fn clear_prepared_derivative_cache(&self) -> Result<()>
pub fn clear_prepared_derivative_cache(&self) -> Result<()>
Clear prepared derivative program cache entries.
§Examples
use tenferro_ad::EagerRuntime;
let ctx = EagerRuntime::new()?;
ctx.clear_prepared_derivative_cache()?;
assert_eq!(ctx.cache_stats()?.prepared_derivatives.entries, 0);§Errors
Returns tenferro_runtime::Error::RuntimeState if the prepared
derivative cache lock is poisoned.
Sourcepub fn cache_stats(&self) -> Result<EagerRuntimeCacheStats>
pub fn cache_stats(&self) -> Result<EagerRuntimeCacheStats>
Return eager runtime cache-entry and retained-byte stats.
§Examples
use tenferro_ad::{EagerRuntime};
let ctx = EagerRuntime::new()?;
let stats = ctx.cache_stats()?;
assert_eq!(stats.ad_transforms.entries, 0);
assert_eq!(stats.prepared_derivatives.entries, 0);§Errors
Returns tenferro_runtime::Error::RuntimeState when a cache or
AD-transform cache lock is poisoned.
Sourcepub fn ad_transform_cache_limits(&self) -> Result<AdTransformCacheLimits>
pub fn ad_transform_cache_limits(&self) -> Result<AdTransformCacheLimits>
Return the AD transform cache retention limits.
§Examples
use tenferro_ad::EagerRuntime;
let ctx = EagerRuntime::new()?;
assert!(ctx.ad_transform_cache_limits()?.max_entries().get() > 0);§Errors
Returns tenferro_runtime::Error::RuntimeState if the AD-transform
cache lock is poisoned.
Sourcepub fn set_ad_transform_cache_limits(
&self,
limits: AdTransformCacheLimits,
) -> Result<()>
pub fn set_ad_transform_cache_limits( &self, limits: AdTransformCacheLimits, ) -> Result<()>
Replace AD transform cache retention limits.
§Examples
use std::num::NonZeroUsize;
use tenferro_ad::{AdTransformCacheLimits, EagerRuntime};
let ctx = EagerRuntime::new()?;
let limits = AdTransformCacheLimits::new(NonZeroUsize::new(1).unwrap());
ctx.set_ad_transform_cache_limits(limits)?;
assert_eq!(ctx.ad_transform_cache_limits()?, limits);§Errors
Returns tenferro_runtime::Error::RuntimeState if the AD-transform
cache lock is poisoned while updating limits.
Sourcepub fn clear_ad_transform_caches(&self) -> Result<()>
pub fn clear_ad_transform_caches(&self) -> Result<()>
Clear AD transform cache entries visible through this eager runtime.
§Examples
use tenferro_ad::EagerRuntime;
let ctx = EagerRuntime::new()?;
ctx.clear_ad_transform_caches()?;
assert_eq!(ctx.cache_stats()?.ad_transforms.entries, 0);§Errors
Returns tenferro_runtime::Error::RuntimeState if the AD-transform
cache lock is poisoned while clearing entries.
Sourcepub fn prepared_derivative_cache_limits(&self) -> Result<AdTransformCacheLimits>
pub fn prepared_derivative_cache_limits(&self) -> Result<AdTransformCacheLimits>
Return prepared derivative cache retention limits.
§Examples
use tenferro_ad::EagerRuntime;
let ctx = EagerRuntime::new()?;
assert!(ctx.prepared_derivative_cache_limits()?.max_entries().get() > 0);§Errors
Returns tenferro_runtime::Error::RuntimeState if the prepared
derivative cache lock is poisoned.
Sourcepub fn set_prepared_derivative_cache_limits(
&self,
limits: AdTransformCacheLimits,
) -> Result<()>
pub fn set_prepared_derivative_cache_limits( &self, limits: AdTransformCacheLimits, ) -> Result<()>
Replace prepared derivative cache retention limits.
§Examples
use std::num::NonZeroUsize;
use tenferro_ad::{AdTransformCacheLimits, EagerRuntime};
let ctx = EagerRuntime::new()?;
let limits = AdTransformCacheLimits::new(NonZeroUsize::new(1).unwrap());
ctx.set_prepared_derivative_cache_limits(limits)?;
assert_eq!(ctx.prepared_derivative_cache_limits()?, limits);§Errors
Returns tenferro_runtime::Error::RuntimeState if the prepared
derivative cache lock is poisoned.
Sourcepub fn with_eager_session<T, E: From<Error>>(
self: &Arc<Self>,
engine: &mut dyn ExecutionEngine,
f: impl FnOnce(&mut EagerSession<'_>) -> Result<T, E>,
) -> Result<T, E>
pub fn with_eager_session<T, E: From<Error>>( self: &Arc<Self>, engine: &mut dyn ExecutionEngine, f: impl FnOnce(&mut EagerSession<'_>) -> Result<T, E>, ) -> Result<T, E>
Run eager operations on engine.
The callback receives an EagerSession that pairs this runtime with
the borrowed engine; operations recorded through it are differentiable.
Nothing is entered or locked: the engine is simply borrowed for the
callback.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
use tenferro_cpu::CpuEngine;
let ctx = EagerRuntime::new()?;
let mut engine = CpuEngine::serial();
let x = EagerTensor::from_tensor_in(Tensor::from_vec_col_major(vec![1], vec![1.0_f64])?, ctx.clone())?;
let y = EagerTensor::from_tensor_in(Tensor::from_vec_col_major(vec![1], vec![2.0_f64])?, ctx.clone())?;
let z = ctx.with_eager_session(&mut engine, |s| s.add(&x, &y))?;
assert_eq!(z.value()?.as_slice::<f64>()?, &[3.0]);§Errors
Returns Error::Unsupported when the engine kind cannot be registered
with this runtime or its context identity conflicts with the existing
registration, Error::RuntimeStateSource when the runtime snapshot or
engine registration state is unavailable, and the callback’s own error
unchanged.
Sourcepub fn clear_grads(&self) -> Result<()>
pub fn clear_grads(&self) -> Result<()>
Clear all live gradient slots tracked by this context.
This resets the stored gradients to None without unregistering the
tensors, so future backward() calls can accumulate again.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let x = EagerTensor::requires_grad_in(Tensor::from_vec_col_major(vec![3], vec![1.0_f64, 2.0, 3.0]).unwrap(), ctx.clone()).unwrap();
let y = EagerTensor::requires_grad_in(Tensor::from_vec_col_major(vec![3], vec![4.0_f64, 5.0, 6.0]).unwrap(), ctx.clone()).unwrap();
let loss = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| {
let product = s.mul(&x, &y)?;
s.reduce_sum(&product, Some(&[0]))
})?;
let _ = loss.backward(&mut tenferro_cpu::CpuEngine::serial()).unwrap();
ctx.clear_grads()?;
assert!(x.grad()?.is_none());
assert!(y.grad()?.is_none());§Errors
Returns tenferro_runtime::Error::RuntimeState if a gradient-slot
lock is poisoned while clearing live gradients.
Sourcepub fn constant_from(self: &Arc<Self>, tensor: Tensor) -> Result<EagerTensor>
pub fn constant_from(self: &Arc<Self>, tensor: Tensor) -> Result<EagerTensor>
Import a concrete tensor into this context as an untracked constant.
The returned tensor does not participate in gradient tracking.
Use this for fixed masks, quadrature weights, physical constants,
and other data that should not receive gradients. Like
EagerSession::constant_from, it performs no host/device transfer;
use EagerSession::constant_from_host to upload host data into a
device runtime.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let c = ctx.constant_from(Tensor::from_vec_col_major(vec![2], vec![1.0_f64, 2.0]).unwrap())?;
let x = EagerTensor::requires_grad_in(Tensor::from_vec_col_major(vec![2], vec![3.0_f64, 4.0]).unwrap(), ctx.clone())?;
let z = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| s.add(&x, &c))?;
assert_eq!(z.value()?.as_slice::<f64>().unwrap(), &[4.0, 6.0]);§Errors
Returns tenferro_runtime::Error::RuntimeState when metadata cannot
be registered or the backend lock is poisoned.
Sourcepub fn variable_from(self: &Arc<Self>, tensor: Tensor) -> Result<EagerTensor>
pub fn variable_from(self: &Arc<Self>, tensor: Tensor) -> Result<EagerTensor>
Import a concrete tensor into this context as a trainable variable.
The returned tensor participates in gradient tracking; its gradient slot is registered in this context.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let p = ctx.variable_from(Tensor::from_vec_col_major(vec![2], vec![1.0_f64, 2.0]).unwrap())?;
let loss = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| {
let y = s.exp(&p)?;
s.reduce_sum(&y, Some(&[0]))
})?;
let _ = loss.backward(&mut tenferro_cpu::CpuEngine::serial()).unwrap();
let grad = p.grad().unwrap().unwrap();
assert_eq!(grad.shape(), &[2]);§Errors
Returns tenferro_runtime::Error::RuntimeState when gradient metadata
or the eager backend state cannot be registered.
Sourcepub fn grad(
self: &Arc<Self>,
engine: &mut dyn ExecutionEngine,
output: &EagerTensor,
wrt: &EagerTensor,
) -> Result<EagerTensor>
pub fn grad( self: &Arc<Self>, engine: &mut dyn ExecutionEngine, output: &EagerTensor, wrt: &EagerTensor, ) -> Result<EagerTensor>
Gradient of a scalar eager output with respect to an eager tensor.
Functional eager gradients return ordinary eager tensors and do not
write into grad() slots. The returned tensor keeps a trace when the
derivative computation depends on tracked eager values.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![], vec![3.0_f64]).unwrap(),
ctx.clone(),
)?;
let loss = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| s.mul(&x, &x))?;
let dx = ctx.grad(&mut tenferro_cpu::CpuEngine::serial(), &loss, &x)?;
assert_eq!(dx.value()?.as_slice::<f64>().unwrap(), &[6.0]);§Errors
Returns tenferro_runtime::Error::NonScalarGrad for a non-scalar
output, Error::ContextMismatch for tensors from another runtime,
Error::UnsupportedAdRule when an AD rule is unavailable, or a typed
validation/backend error from eager execution. An inactive wrt returns
Error::Validation with argument: "wrt"; use
grad_optional to observe that state.
Sourcepub fn grad_optional(
self: &Arc<Self>,
engine: &mut dyn ExecutionEngine,
output: &EagerTensor,
wrt: &EagerTensor,
) -> Result<Option<EagerTensor>>
pub fn grad_optional( self: &Arc<Self>, engine: &mut dyn ExecutionEngine, output: &EagerTensor, wrt: &EagerTensor, ) -> Result<Option<EagerTensor>>
Gradient that returns None when wrt is inactive.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![], vec![3.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![], vec![4.0_f64]).unwrap(),
ctx.clone(),
)?;
let loss = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| s.mul(&y, &y))?;
assert!(ctx.grad_optional(&mut tenferro_cpu::CpuEngine::serial(), &loss, &x)?.is_none());§Errors
Returns tenferro_runtime::Error::NonScalarGrad for a non-scalar
output, Error::ContextMismatch for a foreign runtime, or a typed
validation/backend/runtime-state error from eager execution.
Sourcepub fn vjp(
self: &Arc<Self>,
engine: &mut dyn ExecutionEngine,
output: &EagerTensor,
wrt: &EagerTensor,
cotangent: &EagerTensor,
) -> Result<EagerTensor>
pub fn vjp( self: &Arc<Self>, engine: &mut dyn ExecutionEngine, output: &EagerTensor, wrt: &EagerTensor, cotangent: &EagerTensor, ) -> Result<EagerTensor>
Reverse-mode vector-Jacobian product for eager tensors.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![2], vec![2.0_f64, 3.0]).unwrap(),
ctx.clone(),
)?;
let y = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| s.mul(&x, &x))?;
let seed = EagerTensor::from_tensor_in(
Tensor::from_vec_col_major(vec![2], vec![1.0_f64, 1.0]).unwrap(),
ctx.clone(),
)?;
let dx = ctx.vjp(&mut tenferro_cpu::CpuEngine::serial(), &y, &x, &seed)?;
assert_eq!(dx.value()?.as_slice::<f64>().unwrap(), &[4.0, 6.0]);§Errors
Returns Error::ContextMismatch for tensors from different eager
runtimes, Error::Validation when the cotangent shape or dtype does
not match the output, Error::UnsupportedAdRule when a rule is not
registered, or a typed backend/runtime-state error. An inactive wrt
returns Error::Validation with argument: "wrt"; use
vjp_optional to observe that state.
Sourcepub fn vjp_optional(
self: &Arc<Self>,
engine: &mut dyn ExecutionEngine,
output: &EagerTensor,
wrt: &EagerTensor,
cotangent: &EagerTensor,
) -> Result<Option<EagerTensor>>
pub fn vjp_optional( self: &Arc<Self>, engine: &mut dyn ExecutionEngine, output: &EagerTensor, wrt: &EagerTensor, cotangent: &EagerTensor, ) -> Result<Option<EagerTensor>>
Reverse-mode vector-Jacobian product that returns None for inactive inputs.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![2.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![4.0_f64]).unwrap(),
ctx.clone(),
)?;
let seed = EagerTensor::from_tensor_in(
Tensor::from_vec_col_major(vec![1], vec![1.0_f64]).unwrap(),
ctx.clone(),
)?;
let loss = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| s.mul(&y, &y))?;
assert!(ctx.vjp_optional(&mut tenferro_cpu::CpuEngine::serial(), &loss, &x, &seed)?.is_none());§Errors
Returns Error::ContextMismatch for tensors from different eager
runtimes, Error::Validation when the cotangent shape or dtype does
not match the output, Error::UnsupportedAdRule when a rule is not
registered, or a typed backend/runtime-state error.
Sourcepub fn jvp(
self: &Arc<Self>,
engine: &mut dyn ExecutionEngine,
output: &EagerTensor,
wrt: &EagerTensor,
tangent: &EagerTensor,
) -> Result<EagerTensor>
pub fn jvp( self: &Arc<Self>, engine: &mut dyn ExecutionEngine, output: &EagerTensor, wrt: &EagerTensor, tangent: &EagerTensor, ) -> Result<EagerTensor>
Forward-mode Jacobian-vector product for eager tensors.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![3.0_f64]).unwrap(),
ctx.clone(),
)?;
let tangent = EagerTensor::from_tensor_in(
Tensor::from_vec_col_major(vec![1], vec![1.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| s.mul(&x, &x))?;
let dy = ctx.jvp(&mut tenferro_cpu::CpuEngine::serial(), &y, &x, &tangent)?;
assert_eq!(dy.value()?.as_slice::<f64>().unwrap(), &[6.0]);§Errors
Returns Error::ContextMismatch for tensors from different eager
runtimes, Error::Validation when the tangent shape or dtype does not
match wrt, Error::UnsupportedAdRule when a rule is unavailable, or
a typed backend/runtime-state error. An inactive wrt returns
Error::Validation with argument: "wrt"; use
jvp_optional to observe that state.
Sourcepub fn jvp_optional(
self: &Arc<Self>,
engine: &mut dyn ExecutionEngine,
output: &EagerTensor,
wrt: &EagerTensor,
tangent: &EagerTensor,
) -> Result<Option<EagerTensor>>
pub fn jvp_optional( self: &Arc<Self>, engine: &mut dyn ExecutionEngine, output: &EagerTensor, wrt: &EagerTensor, tangent: &EagerTensor, ) -> Result<Option<EagerTensor>>
Forward-mode Jacobian-vector product that returns None for inactive outputs.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::new()?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![2.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![4.0_f64]).unwrap(),
ctx.clone(),
)?;
let tangent = EagerTensor::from_tensor_in(
Tensor::from_vec_col_major(vec![1], vec![1.0_f64]).unwrap(),
ctx.clone(),
)?;
let loss = ctx.with_eager_session(&mut tenferro_cpu::CpuEngine::serial(), |s| s.mul(&y, &y))?;
assert!(ctx.jvp_optional(&mut tenferro_cpu::CpuEngine::serial(), &loss, &x, &tangent)?.is_none());§Errors
Returns Error::ContextMismatch for tensors from different eager
runtimes, Error::Validation when the tangent shape or dtype does not
match wrt, Error::UnsupportedAdRule when a rule is unavailable, or
a typed backend/runtime-state error.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for EagerRuntime
impl !RefUnwindSafe for EagerRuntime
impl !UnwindSafe for EagerRuntime
impl Send for EagerRuntime
impl Sync for EagerRuntime
impl Unpin for EagerRuntime
impl UnsafeUnpin for EagerRuntime
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
impl<T, U> Imply<T> for U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more