9 个版本 (5 个稳定)
2.2.0 | 2020 年 1 月 11 日 |
---|---|
2.1.0 |
|
2.0.0 | 2019 年 4 月 17 日 |
1.2.1 | 2019 年 3 月 30 日 |
0.3.0 |
|
#1171 在 Rust 模式
1,478 每月下载量
在 3 个crate中使用 3 (2 直接)
12KB
147 行
RecurFn
一个提供更灵活方式来构建和扩展递归函数的 Rust 库。
文档:API 参考。
用法
将以下内容添加到您的 Cargo.toml
[dependencies]
recur-fn = "2.2"
lib.rs
:
一个提供更灵活方式来构建和扩展递归函数的库。
RecurFn
trait 是递归函数的一种抽象。通过接受一个名为 recur
的函数参数作为递归,而不是直接递归,使得构建匿名递归函数成为可能。
use recur_fn::{recur_fn, RecurFn};
let fib = recur_fn(|fib, n: i32| {
if n <= 1 {
n
} else {
fib(n - 1) + fib(n - 2)
}
});
assert_eq!(55, fib.call(10));
此外,它还使扩展递归函数体成为可能。
use recur_fn::{recur_fn, RecurFn};
use std::cell::RefCell;
let fib = recur_fn(|fib, n: i32| {
if n <= 1 {
n
} else {
fib(n - 1) + fib(n - 2)
}
});
let log = RefCell::new(Vec::new());
let fib_with_logging = recur_fn(|recur, n: i32| {
log.borrow_mut().push(n);
fib.body(recur, n)
});
fib_with_logging.call(3);
assert_eq!(*log.borrow(), vec![3, 2, 1, 0, 1]);
由于 recur_fn
是构建 RecurFn
的一种便捷方式,因此调用它比直接递归慢。为了使其成为零成本的,请考虑定义一个结构体,为其实现 RecurFn
trait,并使用 #[inline]
标记 body
方法。
use recur_fn::RecurFn;
let fib = {
struct Fib {}
impl RecurFn<i32, i32> for Fib {
#[inline]
fn body(&self, fib: impl Fn(i32) -> i32, n: i32) -> i32 {
if n <= 1 {
n
} else {
fib(n - 1) + fib(n - 2)
}
}
}
Fib {}
};
assert_eq!(55, fib.call(10));
或者如果函数没有捕获任何内容,您可以使用 recur_fn
宏。
use recur_fn::{recur_fn, RecurFn};
let fact = recur_fn!(fact(n: i32) -> i32 {
if n == 0 { 1 } else { n * fact(n - 1) }
});
assert_eq!(6, fact.call(3));
assert_eq!(0,
fact.body(|_| 0, 3));
DynRecurFn
是 RecurFn
的动态版本,允许您拥有 trait 对象。
use recur_fn::{recur_fn, RecurFn, DynRecurFn};
use core::ops::Deref;
let dyn_fact: &dyn DynRecurFn<_, _> =
&recur_fn(|fact, n: i32| if n == 0 { 1 } else { n * fact(n - 1) });