是否可以在运行时组合函数链? [英] Is it possible to compose a chain of functions at runtime?

查看:48
本文介绍了是否可以在运行时组合函数链?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 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 的输入:

One functional technique is chaining — connecting the output of function A to the input of function B:

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

这在 Rust 中可能会有帮助,因为这个方法是纯函数式的,函数也可以是纯函数;它们不涉及全局变量,仅适用于移动的参数(这很棒).

This may help in Rust because this method is purely functional and the functions can be pure functions; they don't touch global variables, only work with its arguments which were moved (which is awesome).

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

How can I do this chain at runtime? If I have function f4 which accepts the input of f2 but does not use it as f3. We can also use it for further chaining by adding a return type to it:

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

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

我希望能够决定如何在运行时链接我的函数.示例将是此 Lua 代码(对此表示抱歉):

I want to be able to decide how to chain my functions at runtime. The example would be this Lua code (sorry for this):

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++ 具有更多功能.是否可以以这种方式链接功能?

This is a big plus of dynamic typing of scripting languages, but as far as I know Rust alleges that it is much more functional than C++ for example. Is it possible to chain the functions in such a way?

推荐答案

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

Here's how you can do the simple chaining issue. Converting it from free functions to a builder or operator style is left as an exercise. It also uses the "impl Trait" feature introduced in Rust 1.26 to make it nicer.

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(());
}

游乐场

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

Gluing two functions together is not very hard, but you may run into lifetime issues if your types are more complex. In particular, if the input parameter to a function in the chain is a reference to the type that the previous function returns, this code will not compile. I believe that some more parameters and generic bounds can solve this issue, but you would have to experiment a bit.

另请参阅工具箱(compose几乎就是我刚刚发布的内容)和 rustz crate,这两者都为 Rust 添加了更多功能习语.

See also the tool crate (compose is pretty much what I just posted) and the rustz crate, both of which add more functional idioms to Rust.

这篇关于是否可以在运行时组合函数链?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆