Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Method

Specify hooked methods via #[hooq::method(...)] or by flavors. The ... has two modes:

  • If it starts with ., it is in insertion mode, inserting the method between the expression and ? (or at the end for return/tail).
  • Otherwise it is in replacement mode, replacing the expression. Use $expr to reference the original expression (already recursively hooked where needed).

Meta variables (see Meta Variables) can be used in these expressions.

Insertion Mode

use hooq::hooq;

fn failable<T>(val: T) -> Result<T, String> {
    Ok(val)
}

#[hooq]
#[hooq::method(.inspect_err(|_| {
    let _ = "inserted mode";
}))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
    failable(())?;

    #[hooq::method(.inspect_err(|_| {
        let _ = "before chainned";
    }).$so_far)]
    failable(())?;

    #[hooq::method(.$so_far.inspect_err(|_| {
        let _ = "after chainned";
    }))]
    failable(())?;

    Ok(())
}

You can chain with .$so_far to prepend/append relative to the existing chain.

Expansion:

#![feature(prelude_import)]
#[macro_use]
extern crate std;
#[prelude_import]
use std::prelude::rust_2024::*;
use hooq::hooq;
fn failable<T>(val: T) -> Result<T, String> {
    Ok(val)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
    failable(())
        .inspect_err(|_| {
            let _ = "inserted mode";
        })?;
    failable(())
        .inspect_err(|_| {
            let _ = "before chainned";
        })
        .inspect_err(|_| {
            let _ = "inserted mode";
        })?;
    failable(())
        .inspect_err(|_| {
            let _ = "inserted mode";
        })
        .inspect_err(|_| {
            let _ = "after chainned";
        })?;
    Ok(())
}

Replacement Mode

If it does not start with . (dot), it is treated as a replacement function, replacing the original expression with the configured expression. The expression being replaced can be accessed using the $expr meta variable. (While it’s possible to write without using $expr, it would likely not be useful.)

use hooq::hooq;

fn failable<T>(val: T) -> Result<T, String> {
    Ok(val)
}

fn wrapper<T, E>(r: Result<T, E>) -> Result<T, E>
where
    E: std::fmt::Debug,
{
    if let Err(e) = &r {
        println!("Error occurred: {:?}", e);
    }

    r
}

#[hooq]
#[hooq::method(wrapper($expr))]
fn main() -> Result<(), String> {
    failable(())?;

    Ok(())
}

Expansion:

#![feature(prelude_import)]
#[macro_use]
extern crate std;
#[prelude_import]
use std::prelude::rust_2024::*;
use hooq::hooq;
fn failable<T>(val: T) -> Result<T, String> {
    Ok(val)
}
fn wrapper<T, E>(r: Result<T, E>) -> Result<T, E>
where
    E: std::fmt::Debug,
{
    if let Err(e) = &r {
        {
            ::std::io::_print(format_args!("Error occurred: {0:?}\n", e));
        };
    }
    r
}
fn main() -> Result<(), String> {
    wrapper(failable(()))?;
    Ok(())
}

Use $expr (not $source) in replacement mode. $expr holds the expression after inner hooks have been applied, while $source is for logging/display of the original tokens.

Removing ? via Trailing !

When hooking the ? operator, appending ! to the method consumes the trailing ?.

Requires the consume-question feature.

cargo add hooq --features consume-question

Example aliasing ? to .unwrap():

use hooq::hooq;

fn failable<T>(val: T) -> Result<T, &'static str> {
    Ok(val)
}

#[hooq]
#[hooq::hook_targets("?")]
#[hooq::method(.unwrap()!)]
fn main() {
    failable(())?;
}

Expansion:

#![feature(prelude_import)]
#[macro_use]
extern crate std;
#[prelude_import]
use std::prelude::rust_2024::*;
use hooq::hooq;
fn failable<T>(val: T) -> Result<T, &'static str> {
    Ok(val)
}
fn main() {
    failable(()).unwrap();
}