ProductPromotion
Logo

Rust

made by https://0x3d.site

GitHub - myrrlyn/tap: Generic extensions for tapping values in Rust.
Generic extensions for tapping values in Rust. Contribute to myrrlyn/tap development by creating an account on GitHub.
Visit Site

GitHub - myrrlyn/tap: Generic extensions for tapping values in Rust.

GitHub - myrrlyn/tap: Generic extensions for tapping values in Rust.

tap

Suffix-Position Pipeline Behavior

Crate Documentation License

Crate Downloads Crate Size

This crate provides extension methods on all types that allow transparent, temporary, inspection/mutation (tapping), transformation (piping), or type conversion. These methods make it convenient for you to insert debugging or modification points into an expression without requiring you to change any other portions of your code.

Example Use

Tapping

You can tap inside a method-chain expression for logging without requiring a rebind. For instance, you may write a complex expression without any intermediate debugging steps, and only later decide that you want them. Ordinarily, this transform would look like this:

extern crate reqwest;
extern crate tracing;

// old
let body = reqwest::blocking::get("https://example.com")?
  .text()?;
tracing::debug!("Response contents: {}", body);

// new, with debugging
let resp = reqwest::blocking::get("https://example.com")?;
tracing::debug!("Response status: {}", resp.status());
let body = resp.text()?;
tracing::debug!("Response contents: {}", body);

while with tapping, you can plug the logging statement directly into the overall expression, without making any other changes:

extern crate reqwest;
extern crate tracing;

let body = reqwest::blocking::get("https://example.com")?
  // The only change is the insertion of this line
  .tap(|resp| tracing::debug!("Response status: {}", resp.status()))
  .text()?;
tracing::debug!("Response contents: {}", body);

Mutable Tapping

Some APIs are written to require mutable borrows, rather than value-to-value transformations, which can require temporary rebinding in order to create mutability in an otherwise-immutable context. For example, collecting data into a vector, sorting the vector, and then freezing it, might look like this:

let mut collection = stream().collect::<Vec<_>>();
collection.sort();
// potential error site: inserting other mutations here
let collection = collection; // now immutable

But with a mutable tap, you can avoid the duplicate binding and guard against future errors due to the presence of a mutable binding:

let collection = stream.collect::<Vec<_>>()
  .tap_mut(|v| v.sort());

The .tap_mut() and related methods provide a mutable borrow to their argument, and allow the final binding site to choose their own level of mutability without exposing the intermediate permission.

Piping

In addition to transparent inspection or modification points, you may also wish to use suffix calls for subsequent operations. For example, the standard library offers the free function fs::read to convert Path-like objects into Vec<u8> of their filesystem contents. Ordinarily, free functions require use as:

use std::fs;

let mut path = get_base_path();
path.push("logs");
path.push(&format!("{}.log", today()));
let contents = fs::read(path)?;

whereäs use of tapping (for path modification) and piping (for fs::read) could be expressed like this:

use std::fs;

let contents = get_base_path()
  .tap_mut(|p| p.push("logs"))
  .tap_mut(|p| p.push(&format!("{}.log", today())))
  .pipe(fs::read)?;

As a clearer example, consider the syntax required to apply multiple free funtions without let-bindings looks like this:

let val = last(
  third(
    second(
      first(original_value),
      another_arg,
    )
  ),
  another_arg,
);

which requires reading the expression in alternating, inside-out, order, to understand the full sequence of evaluation. With suffix calls, even free functions can be written in a point-free style that maintains a clear temporal and syntactic order:

let val = original_value
  .pipe(first)
  .pipe(|v| second(v, another_arg))
  .pipe(third)
  .pipe(|v| last(v, another_arg));

As piping is an ordinary method, not a syntax transformation, it still requires that you write function-call expressions when using a function with multiple arguments in the pipeline.

Conversion

The conv module is the simplest: it provides two traits, Conv and TryConv, which are sibling traits to Into<T> and TryInto<T>. Their methods, Conv::conv::<T> and TryConv::try_conv::<T>, call the corresponding trait implementation, and allow you to use .into()/.try_into() in non-terminal method calls of an expression.

let bytes = "hello".into().into_bytes();

does not compile, because Rust cannot decide the type of "hello".into(). Instead of rewriting the expression to use an intermediate let binding, you can write it as

let bytes = "hello".conv::<String>().into_bytes();

Full Functionality

The Tap and Pipe traits both provide a large number of methods, which use different parts of the Rust language’s facilities for well-typed value access. Rather than repeat the API documentation here, you should view the module items in the documentation.

As a summary, these traits provide methods that, upon receipt of a value,

  • apply no transformation
  • apply an AsRef or AsMut implementation
  • apply a Borrow or BorrowMut implementation
  • apply the Deref or DerefMut implementation

before executing their effect argument.

In addition, each Tap method .tap_x has a sibling method .tap_x_dbg that performs the same work, but only in debug builds; in release builds, the method call is stripped. This allows you to leave debugging taps in your source code, without affecting your project’s performance in true usage.

Lastly, the tap module also has traits TapOptional and TapFallible which run taps on the variants of Option and Result enums, respectively, and do nothing when the variant does not match the method name. TapOptional::tap_some has no effect when called on a None, etc.

More Resources
to explore the angular.

mail [email protected] to add your project or resources here 🔥.

Related Articles
to learn about angular.

FAQ's
to learn more about Angular JS.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory