Skip to content

Commit 0c2688e

Browse files
committed
Trial using Try with TapFallible
1 parent f5315f0 commit 0c2688e

3 files changed

Lines changed: 56 additions & 162 deletions

File tree

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(try_trait_v2)]
12
/*! # `tap` – Syntactical Plumb-Lines
23
34
Rust permits functions that take a `self` receiver to be written in “dot-call”

src/tap.rs

Lines changed: 50 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ make_vec().tap_deref_mut(<[_]>::sort);
3131
// make_vec().tap_mut(Vec::sort);
3232
```
3333
!*/
34-
34+
use core::ops::{ControlFlow, Try};
3535
use core::{
3636
borrow::{Borrow, BorrowMut},
3737
ops::{Deref, DerefMut},
@@ -328,120 +328,6 @@ where
328328

329329
impl<T> Tap for T where T: Sized {}
330330

331-
/** Optional tapping, conditional on the optional presence of a value.
332-
333-
This trait is intended for use on types that express the concept of “optional
334-
presence”, primarily the [`Option`] monad. It provides taps that inspect the
335-
container to determine if the effect function should execute or not.
336-
337-
> Note: This trait is a specialization of [`TapFallible`], and exists because
338-
> the [`std::ops::Try`] trait is still unstable. When `Try` stabilizes, this
339-
> trait can be removed, and `TapFallible` blanket-applied to all `Try`
340-
> implementors.
341-
342-
[`Option`]: https://doc.rust-lang.org/std/option/enum.Option.html
343-
[`TapFallible`]: trait.TapFallible.html
344-
[`std::ops::Try`]: https://doc.rust-lang.org/std/ops/trait.Try.html
345-
**/
346-
pub trait TapOptional
347-
where
348-
Self: Sized,
349-
{
350-
/// The interior type that the container may or may not carry.
351-
type Val: ?Sized;
352-
353-
/// Immutabily accesses an interior value only when it is present.
354-
///
355-
/// This function is identical to [`Tap::tap`], except that it is required
356-
/// to check the implementing container for value presence before running.
357-
/// Implementors must not run the effect function if the container is marked
358-
/// as being empty.
359-
///
360-
/// [`Tap::tap`]: trait.Tap.html#method.tap
361-
fn tap_some(self, func: impl FnOnce(&Self::Val)) -> Self;
362-
363-
/// Mutably accesses an interor value only when it is present.
364-
///
365-
/// This function is identical to [`Tap::tap_mut`], except that it is
366-
/// required to check the implementing container for value presence before
367-
/// running. Implementors must not run the effect function if the container
368-
/// is marked as being empty.
369-
///
370-
/// [`Tap::tap_mut`]: trait.Tap.html#method.tap_mut
371-
fn tap_some_mut(self, func: impl FnOnce(&mut Self::Val)) -> Self;
372-
373-
/// Runs an effect function when the container is empty.
374-
///
375-
/// This function is identical to [`Tap::tap`], except that it is required
376-
/// to check the implementing container for value absence before running.
377-
/// Implementors must not run the effect function if the container is marked
378-
/// as being non-empty.
379-
///
380-
/// [`Tap::tap`]: trait.Tap.html#method.tap
381-
fn tap_none(self, func: impl FnOnce()) -> Self;
382-
383-
/// Calls `.tap_some()` only in debug builds, and is erased in release
384-
/// builds.
385-
#[inline(always)]
386-
fn tap_some_dbg(self, func: impl FnOnce(&Self::Val)) -> Self {
387-
if cfg!(debug_assertions) {
388-
self.tap_some(func)
389-
} else {
390-
self
391-
}
392-
}
393-
394-
/// Calls `.tap_some_mut()` only in debug builds, and is erased in release
395-
/// builds.
396-
#[inline(always)]
397-
fn tap_some_mut_dbg(self, func: impl FnOnce(&mut Self::Val)) -> Self {
398-
if cfg!(debug_assertions) {
399-
self.tap_some_mut(func)
400-
} else {
401-
self
402-
}
403-
}
404-
405-
/// Calls `.tap_none()` only in debug builds, and is erased in release
406-
/// builds.
407-
#[inline(always)]
408-
fn tap_none_dbg(self, func: impl FnOnce()) -> Self {
409-
if cfg!(debug_assertions) {
410-
self.tap_none(func)
411-
} else {
412-
self
413-
}
414-
}
415-
}
416-
417-
impl<T> TapOptional for Option<T> {
418-
type Val = T;
419-
420-
#[inline(always)]
421-
fn tap_some(self, func: impl FnOnce(&T)) -> Self {
422-
if let Some(ref val) = self {
423-
func(val);
424-
}
425-
self
426-
}
427-
428-
#[inline(always)]
429-
fn tap_some_mut(mut self, func: impl FnOnce(&mut T)) -> Self {
430-
if let Some(ref mut val) = self {
431-
func(val);
432-
}
433-
self
434-
}
435-
436-
#[inline(always)]
437-
fn tap_none(self, func: impl FnOnce()) -> Self {
438-
if self.is_none() {
439-
func();
440-
}
441-
self
442-
}
443-
}
444-
445331
/** Fallible tapping, conditional on the optional success of an expression.
446332
447333
This trait is intended for use on types that express the concept of “fallible
@@ -457,14 +343,8 @@ container to determine if the effect function should execute or not.
457343
**/
458344
pub trait TapFallible
459345
where
460-
Self: Sized,
346+
Self: Sized + Try,
461347
{
462-
/// The interior type used to indicate a successful construction.
463-
type Ok: ?Sized;
464-
465-
/// The interior type used to indicate a failed construction.
466-
type Err: ?Sized;
467-
468348
/// Immutably accesses an interior success value.
469349
///
470350
/// This function is identical to [`Tap::tap`], except that it is required
@@ -473,7 +353,7 @@ where
473353
/// as being a failure.
474354
///
475355
/// [`Tap::tap`]: trait.Tap.html#method.tap
476-
fn tap_ok(self, func: impl FnOnce(&Self::Ok)) -> Self;
356+
fn tap_continue(self, func: impl FnOnce(&Self::Output)) -> Self;
477357

478358
/// Mutably accesses an interior success value.
479359
///
@@ -483,7 +363,7 @@ where
483363
/// is marked as being a failure.
484364
///
485365
/// [`Tap::tap_mut`]: trait.Tap.html#method.tap_mut
486-
fn tap_ok_mut(self, func: impl FnOnce(&mut Self::Ok)) -> Self;
366+
fn tap_continue_mut(self, func: impl FnOnce(&mut Self::Output)) -> Self;
487367

488368
/// Immutably accesses an interior failure value.
489369
///
@@ -493,7 +373,7 @@ where
493373
/// as being a success.
494374
///
495375
/// [`Tap::tap`]: trait.Tap.html#method.tap
496-
fn tap_err(self, func: impl FnOnce(&Self::Err)) -> Self;
376+
fn tap_break(self, func: impl FnOnce(&Self::Residual)) -> Self;
497377

498378
/// Mutably accesses an interior failure value.
499379
///
@@ -503,85 +383,97 @@ where
503383
/// is marked as being a success.
504384
///
505385
/// [`Tap::tap_mut`]: trait.Tap.html#method.tap_mut
506-
fn tap_err_mut(self, func: impl FnOnce(&mut Self::Err)) -> Self;
386+
fn tap_break_mut(self, func: impl FnOnce(&mut Self::Residual)) -> Self;
507387

508-
/// Calls `.tap_ok()` only in debug builds, and is erased in release builds.
388+
/// Calls `.tap_continue()` only in debug builds, and is erased in release builds.
509389
#[inline(always)]
510-
fn tap_ok_dbg(self, func: impl FnOnce(&Self::Ok)) -> Self {
390+
fn tap_ok_dbg(self, func: impl FnOnce(&Self::Output)) -> Self {
511391
if cfg!(debug_assertions) {
512-
self.tap_ok(func)
392+
self.tap_continue(func)
513393
} else {
514394
self
515395
}
516396
}
517397

518-
/// Calls `.tap_ok_mut()` only in debug builds, and is erased in release
398+
/// Calls `.tap_continue_mut()` only in debug builds, and is erased in release
519399
/// builds.
520400
#[inline(always)]
521-
fn tap_ok_mut_dbg(self, func: impl FnOnce(&mut Self::Ok)) -> Self {
401+
fn tap_ok_mut_dbg(self, func: impl FnOnce(&mut Self::Output)) -> Self {
522402
if cfg!(debug_assertions) {
523-
self.tap_ok_mut(func)
403+
self.tap_continue_mut(func)
524404
} else {
525405
self
526406
}
527407
}
528408

529-
/// Calls `.tap_err()` only in debug builds, and is erased in release
409+
/// Calls `.tap_break()` only in debug builds, and is erased in release
530410
/// builds.
531411
#[inline(always)]
532-
fn tap_err_dbg(self, func: impl FnOnce(&Self::Err)) -> Self {
412+
fn tap_err_dbg(self, func: impl FnOnce(&Self::Residual)) -> Self {
533413
if cfg!(debug_assertions) {
534-
self.tap_err(func)
414+
self.tap_break(func)
535415
} else {
536416
self
537417
}
538418
}
539419

540-
/// Calls `.tap_err_mut()` only in debug builds, and is erased in release
420+
/// Calls `.tap_break_mut()` only in debug builds, and is erased in release
541421
/// builds.
542422
#[inline(always)]
543-
fn tap_err_mut_dbg(self, func: impl FnOnce(&mut Self::Err)) -> Self {
423+
fn tap_err_mut_dbg(self, func: impl FnOnce(&mut Self::Residual)) -> Self {
544424
if cfg!(debug_assertions) {
545-
self.tap_err_mut(func)
425+
self.tap_break_mut(func)
546426
} else {
547427
self
548428
}
549429
}
550430
}
551431

552-
impl<T, E> TapFallible for Result<T, E> {
553-
type Ok = T;
554-
type Err = E;
555-
432+
impl<T> TapFallible for T
433+
where
434+
T: Try,
435+
{
556436
#[inline(always)]
557-
fn tap_ok(self, func: impl FnOnce(&T)) -> Self {
558-
if let Ok(ref val) = self {
559-
func(val);
437+
fn tap_continue(self, func: impl FnOnce(&Self::Output)) -> Self {
438+
match self.branch() {
439+
ControlFlow::Continue(output) => {
440+
func(&output);
441+
Self::from_output(output)
442+
}
443+
ControlFlow::Break(residual) => Self::from_residual(residual),
560444
}
561-
self
562445
}
563446

564447
#[inline(always)]
565-
fn tap_ok_mut(mut self, func: impl FnOnce(&mut T)) -> Self {
566-
if let Ok(ref mut val) = self {
567-
func(val);
448+
fn tap_continue_mut(self, func: impl FnOnce(&mut Self::Output)) -> Self {
449+
match self.branch() {
450+
ControlFlow::Continue(mut output) => {
451+
func(&mut output);
452+
Self::from_output(output)
453+
}
454+
ControlFlow::Break(residual) => Self::from_residual(residual),
568455
}
569-
self
570456
}
571457

572458
#[inline(always)]
573-
fn tap_err(self, func: impl FnOnce(&E)) -> Self {
574-
if let Err(ref val) = self {
575-
func(val);
459+
fn tap_break(self, func: impl FnOnce(&Self::Residual)) -> Self {
460+
match self.branch() {
461+
ControlFlow::Continue(output) => Self::from_output(output),
462+
ControlFlow::Break(residual) => {
463+
func(&residual);
464+
Self::from_residual(residual)
465+
}
576466
}
577-
self
578467
}
579468

580469
#[inline(always)]
581-
fn tap_err_mut(mut self, func: impl FnOnce(&mut E)) -> Self {
582-
if let Err(ref mut val) = self {
583-
func(val);
470+
fn tap_break_mut(self, func: impl FnOnce(&mut Self::Residual)) -> Self {
471+
match self.branch() {
472+
ControlFlow::Continue(output) => Self::from_output(output),
473+
ControlFlow::Break(mut residual) => {
474+
func(&mut residual);
475+
Self::from_residual(residual)
476+
}
584477
}
585-
self
586478
}
587479
}

tests/lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(exhaustive_patterns)]
12
extern crate tap;
23

34
use tap::prelude::*;
@@ -9,7 +10,7 @@ fn filter_map() {
910
// It is especially useful in filter maps, allowing error information to
1011
// be logged/printed before the information is discarded.
1112
result
12-
.tap_err(|error| println!("Invalid entry: {}", error))
13+
.tap_break(|Err(error)| println!("Invalid entry: {}", error))
1314
.ok()
1415
});
1516
}
@@ -23,11 +24,11 @@ fn basic() {
2324
assert_eq!(val, 15);
2425
}
2526

26-
// Results have `tap_err` & `tap_ok` available.
27-
let _: Result<i32, i32> = Err(5).tap_err(|e| val = *e);
27+
// Results have `tap_break` & `tap_ok` available.
28+
let _: Result<i32, i32> = Err(5).tap_break(|Err(e)| val = *e);
2829
assert_eq!(val, 5);
2930

3031
// Options have `tap_some` & `tap_none` available.
31-
let _: Option<i32> = None.tap_none(|| val = 10);
32+
let _: Option<i32> = None.tap_break(|None| val = 10);
3233
assert_eq!(val, 10);
3334
}

0 commit comments

Comments
 (0)