#递归 #recur

recur-fn

一个提供更灵活方式来构建和扩展递归函数的库

9 个版本 (5 个稳定)

2.2.0 2020 年 1 月 11 日
2.1.0 2019 年 8 月 14 日
2.0.0 2019 年 4 月 17 日
1.2.1 2019 年 3 月 30 日
0.3.0 2019 年 2 月 8 日

#1171Rust 模式

Download history 286/week @ 2024-03-15 339/week @ 2024-03-22 260/week @ 2024-03-29 361/week @ 2024-04-05 335/week @ 2024-04-12 405/week @ 2024-04-19 404/week @ 2024-04-26 472/week @ 2024-05-03 307/week @ 2024-05-10 405/week @ 2024-05-17 305/week @ 2024-05-24 532/week @ 2024-05-31 402/week @ 2024-06-07 405/week @ 2024-06-14 411/week @ 2024-06-21 185/week @ 2024-06-28

1,478 每月下载量
3crate中使用 3 (2 直接)

MIT/Apache

12KB
147

RecurFn

Build Status

一个提供更灵活方式来构建和扩展递归函数的 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));

DynRecurFnRecurFn 的动态版本,允许您拥有 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) });

无运行时依赖