rust - 是否可以在运行时组合函数链?

标签 rust

我有3个功能:

fn f1() -> u64 {
    println!("Hello world: 1");
    2
}

fn f2(i: u64) -> Box<FnMut()> {
    println!("Hello world: {}", i);
    Box::new(|| println!("Hello world: {}", 3))
}

fn f3(mut f: Box<FnMut()>) {
    f()
}

一种函数技术是链接——将函数 A 的输出连接到函数 B 的输入:

fn main() {
    f3(f2(f1()));
}

这在 Rust 中可能会有所帮助,因为该方法是纯函数式的,并且函数可以是纯函数;它们不触及全局变量,只使用移动的参数(这很棒)。

如何在运行时执行此链?如果我有函数f4,它接受f2的输入,但不将其用作f3。我们还可以通过向其添加返回类型来将其用于进一步链接:

fn f4(_: Box<FnMut()>) -> bool {
    println!("Hello world: 4");
    true
}

fn main() {
    f4(f2(f1())) // returns f4's result (true)
}

我希望能够决定如何在运行时链接我的函数。示例是这个 Lua 代码(抱歉):

function f1()
    print("Hello world: 1")
    return 2
end

function f2(args)
    print("Hello world: " .. args)
    return function()
        print("Hello world: " .. args + 1)
    end
end

function f3(args)
    args()
end

function f4()
    print("Hello world: 4")
end


function run_chain(list)
    local args
    for _, v in ipairs(list) do
        args = v(args)
    end
end

local list = {}
list[#list + 1] = f1
list[#list + 1] = f2
list[#list + 1] = f3
run_chain(list)
list[#list] = f4
run_chain(list)

这是脚本语言动态类型的一大优点,但据我所知,Rust 声称它比 C++ 等功能更强大。是否可以以这种方式链接函数?

最佳答案

以下是解决简单链接问题的方法。将其从自由函数转换为构建器或操作符样式留作练习。它还使用 Rust 1.26 中引入的“impl Trait”功能来使其变得更好。

fn f1(_: ()) -> u64 {
    println!("Hello world: 1");
    2
}
fn f2(i: u64) -> Box<FnMut()> {
    println!("Hello world: {}", i);
    Box::new(|| println!("Hello world: {}", 3))
}
fn f3(mut f: Box<FnMut()>) {
    f()
}
fn f4(_: Box<FnMut()>) -> bool {
    println!("Hello world: 4");
    true
}

fn dot<I, X, O, F1, F2>(mut f1: F1, mut f2: F2) -> impl FnMut(I) -> O
where
    F1: FnMut(I) -> X,
    F2: FnMut(X) -> O,
{
    move |i| f2(f1(i))
}

fn main() {
    let mut c = dot(dot(f1, f2), f3);
    c(());
    let mut c2 = dot(dot(f1, f2), f4);
    c2(());
}

Playground

将两个函数粘合在一起并不是很难,但如果您的类型更复杂,您可能会遇到生命周期问题。特别是,如果链中函数的输入参数是对前一个函数返回的类型的引用,则此代码将无法编译。我相信更多的参数和通用边界可以解决这个问题,但你必须进行一些实验。

另请参阅tool crate (compose 几乎就是我刚刚发布的内容)和 rustz crate ,两者都为 Rust 添加了更多功能性习惯用法。

关于rust - 是否可以在运行时组合函数链?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46805540/

相关文章:

postgresql - 如何连接到 PostgreSQL?

string - 如何在 Rust 中对字符串的字符进行排序?

rust - 了解 Rust 生命周期和借用检查器

multithreading - gtk-rs:如何从另一个线程更新 View

cuda - 使用 cc 更改 Rust 传递给 nvcc 的编译参数

user-interface - 冰镇 : How to create window in fullscreen?

size - bool 保证是 1 个字节吗?

hashmap - 如何为我自己的结构实现 Eq 和 Hash 以将它们用作 HashMap 键?

rust - 如何将 Future 作为函数参数传递?

module - 在 Rust 2018 中使用模块时如何解决错误 "no module in the root"?