Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
forked fromdarfink/tap-rs

Generic extensions for tapping values in Rust.

License

NotificationsYou must be signed in to change notification settings

myrrlyn/tap

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Suffix-Position Pipeline Behavior

CrateDocumentationLicense

Crate DownloadsCrate Size

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

Example Use

Tapping

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

externcrate reqwest;externcrate tracing;// oldlet body = reqwest::blocking::get("https://example.com")?.text()?;tracing::debug!("Response contents: {}", body);// new, with debugginglet 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 overallexpression, without making any other changes:

externcrate reqwest;externcrate 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-valuetransformations, which can require temporary rebinding in order to createmutability in an otherwise-immutable context. For example, collecting data intoa vector, sorting the vector, and then freezing it, might look like this:

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

But with a mutable tap, you can avoid the duplicate bindingand guard againstfuture 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 withoutexposing the intermediate permission.

Piping

In addition to transparent inspection or modification points, you may also wishto use suffix calls for subsequent operations. For example, the standard libraryoffers the free functionfs::read to convertPath-like objects intoVec<u8> of their filesystem contents. Ordinarily, free functions require useas:

use std::fs;letmut 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 (forfs::read) couldbe 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 freefuntions withoutlet-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, tounderstand the full sequence of evaluation. With suffix calls, even freefunctions can be written in a point-free style that maintains a clear temporaland 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 requiresthat you write function-call expressions when using a function with multiplearguments in the pipeline.

Conversion

Theconv module is the simplest: it provides two traits,Conv andTryConv,which are sibling traits toInto<T> andTryInto<T>. Their methods,Conv::conv::<T> andTryConv::try_conv::<T>, call the correspondingtrait implementation, and allow you to use.into()/.try_into() innon-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 intermediatelet binding, youcan write it as

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

Full Functionality

TheTap andPipe traits both provide a large number of methods, which usedifferent parts of the Rust language’s facilities for well-typed value access.Rather than repeat the API documentation here, you should view the module itemsin thedocumentation.

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

  • apply no transformation
  • apply anAsRef orAsMut implementation
  • apply aBorrow orBorrowMut implementation
  • apply theDeref orDerefMut implementation

before executing their effect argument.

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

Lastly, thetap module also has traitsTapOptional andTapFallible whichrun taps on the variants ofOption andResult enums, respectively, and donothing when the variant does not match the method name.TapOptional::tap_somehas no effect when called on aNone, etc.

About

Generic extensions for tapping values in Rust.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust100.0%

[8]ページ先頭

©2009-2025 Movatter.jp