#fake #user-defined #data #ops #fn #type

hackfn

为用户自定义数据类型提供 std::ops::Fn 的模拟实现

9个版本

0.1.8 2022年12月18日
0.1.7 2022年4月24日
0.1.6 2021年12月15日
0.1.4 2020年6月16日
0.1.1 2018年9月8日

#2110 in 过程宏

每月 25 次下载

MIT/Apache

12KB
134

#[hackfn]

github crates.io docs.rs build status

为用户自定义数据类型提供 std::ops::Fn 的模拟实现。

在包含单个方法的 impl 块上放置 #[hackfn] 属性,将该方法用作函数调用操作符的实现。

[dependencies]
hackfn = "0.1"

版本要求:#[hackfn] 支持 rustc 1.31+

限制

  • 函数必须接收 &self。不支持接收 &mut selfself 的函数。

  • 函数可能没有泛型参数或 where 子句。

  • Self 类型必须实现 Sized

示例

use hackfn::hackfn;

/// Function object that adds some number to its input.
struct Plus(u32);

#[hackfn]
impl Plus {
    fn call(&self, other: u32) -> u32 {
        self.0 + other
    }
}

fn main() {
    let plus_one = Plus(1);
    let sum = plus_one(2);
    assert_eq!(sum, 3);
}

下面的示例稍微复杂一些

  • 可以使用内部可变性来近似 FnMut 实现。

  • 在 impl 块上(尽管不在函数上)允许使用泛型参数和 where 子句。

  • 函数可以接受任意数量的参数。

use hackfn::hackfn;

use std::cell::Cell;
use std::ops::Add;

/// Function object that accumulates a pair of values per call.
#[derive(Default)]
struct AccumulatePairs<T> {
    first: Cell<T>,
    second: Cell<T>,
}

#[hackfn]
impl<T> AccumulatePairs<T> where T: Copy + Add<Output = T> {
    fn call(&self, first: T, second: T) {
        self.first.set(self.first.get() + first);
        self.second.set(self.second.get() + second);
    }
}

fn main() {
    let accumulate = AccumulatePairs::default();
    accumulate(30, 1);
    accumulate(20, 2);
    accumulate(10, 3);
    assert_eq!(accumulate.first.get(), 60);
    assert_eq!(accumulate.second.get(), 6);
}

许可证

根据您的选择,许可协议为 Apache License, Version 2.0MIT许可证
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您提交的任何旨在包含在此软件包中的贡献,将按上述方式双许可,而无需任何额外条款或条件。

依赖项

约1.5MB
~36K SLoC