Trait wyz::tap::Tap

source · []
pub trait Tap: Sized {
    fn tap<F, R>(self, func: F) -> Self
    where
        F: FnOnce(&Self) -> R,
        R: Sized
, { ... }
fn tap_dbg<F, R>(self, func: F) -> Self
    where
        F: FnOnce(&Self) -> R,
        R: Sized
, { ... }
fn tap_mut<F, R>(self, func: F) -> Self
    where
        F: FnOnce(&mut Self) -> R,
        R: Sized
, { ... }
fn tap_mut_dbg<F, R>(self, func: F) -> Self
    where
        F: FnOnce(&mut Self) -> R,
        R: Sized
, { ... } }
Expand description

Value Tap

This trait allows any function that takes a borrowed value to be run on a value directly, without downgrading the binding.

Examples

Sorting a vector is a quintessential example of operations that break the flow of handling a value. It cannot be done in the middle of an operation, because it has the signature &mut self -> ().

use wyz::tap::Tap;

let v = vec![5, 1, 4, 2, 3]
  .tap_mut(|v| v.sort())
  .tap_mut(|v| v.reverse())
  .tap_mut(|v| v.iter_mut().for_each(|elt| *elt *= 2));
assert_eq!(&v, &[10, 8, 6, 4, 2]);

Note that because sort and reverse are actually methods on [T: Ord], not on Vec<T: Ord>, they cannot be listed by name in the tap_mut call. Their signature is &mut [T: Ord] -> (), but tap_mut provides a &mut Vec<T: Ord>, and deref-coercion does not apply to named functions. The TapDeref trait allows this to work.

Provided methods

Provides immutable access for inspection.

This is most useful for inserting passive inspection points into an expression, such as for logging or counting.

Examples

This demonstrates the use of tap to inspect a value and log it as it is transformed.

use wyz::tap::Tap;

fn make_value() -> i32 { 5 }
fn alter_value(n: i32) -> i32 { n * 3 }

let mut init_flag = false;
let mut fini_flag = false;
let finished = make_value()
  .tap(|n| init_flag = *n == 5)
  .tap_mut(|n| *n = alter_value(*n))
  .tap(|n| fini_flag = *n == 15);

assert!(init_flag);
assert!(fini_flag);
assert_eq!(finished, 15);

This example is somewhat contrived, since tap is most useful for logging values with eprintln! or the log crate and those are hard to nicely demonstrate in tests.

Calls tap in debug builds, and does nothing in release builds.

Provides mutable access for modification.

This is most useful for transforming mutator methods of the kind &mut self -> () and making them fit in value chains of self -> Self.

Examples

Append to a string without a let mut statement.

use wyz::tap::Tap;
let full: String = "Hello".to_owned()
  .tap_mut(|s| s.push_str(", reader!"));
assert_eq!(full, "Hello, reader!");

Calls tap_mut in debug builds, and does nothing in release builds.

Implementors