没有实参的Rust函数和只有一个未使用实参的函数有什么区别?



制作这样的函数有什么区别:

fn add(_: i32) -> i32 {
    10 + 25
}

还有这个

fn add() -> i32 {
    10 + 25
}

我意识到第一个函数在调用时需要一个参数,即使它没有被使用,所以我认为第二个版本在这种情况下应该是可以的。

是否有任何理由允许我使用第一个版本?我在铁的例子中看到这一点,当实现一个处理程序到某个路由时。我很困惑,为什么它必须是这样的时候,提供一个空参数应该工作

函数签名是调用者和被调用者之间的契约:

  • 它允许调用者确保它传递的参数是合约指定的参数
  • 它允许被调用者确信它收到的参数是合约中指定的参数

而且,也许更重要的是,它强制了一个封装边界:调用方不知道被调用方读取或修改了哪些参数,它所知道的只是合约的要求。

这个封装是这里的驱动因素。这个API的设计是因为一些客户端可能会使用这个值,所以它被传递。特定的客户端是否使用它,是客户端的实现细节,调用者不会(也不应该)关心。

简短的回答:零参数的函数与一个参数的函数具有不同的API和ABI。

长答:

Iron处理器期望一个只有一个参数的函数。如果你可以传递一个没有参数的函数,Iron怎么知道呢?它指定应该有一个参数,这是API需求。即使你丢弃了这个参数也不会改变什么,Iron仍然会将这个参数传递给函数。

如果你(不安全地)传递一个没有参数的函数,那么Iron仍然会传递那个参数,但是函数的代码不需要参数,这样你就引入了未定义的行为。

也就是说,Iron可以提供一些辅助特性,允许您传递零参数函数,但这样做只是引入了您看不到的第二层:

fn short_add() -> i32 {
    add(42) // or another dummy value
}

不同签名的函数是不可互换的,因为ABI是不同的。

虽然你可能认为忽略参数没有什么区别,但你不能依赖它;在某些情况下,这确实很重要。例如,任何带有析构函数的函数都希望被调用函数在返回前销毁形参。

Rust的优势之一是它的强类型系统,默认情况下不允许这样的错误使用(类似于整数转换等);在这个特殊的例子中,添加未命名/未使用的参数是很容易的,所以不是很不方便。

在Rust中,可以传递函数指针和闭包,但是具有不同参数和返回值的函数具有不同的类型。

的例子:

fn test_no_args(f0: fn() -> i32) {
    println!("{}", f0())
} 
fn test_1_arg(f1: fn(i32) -> i32) {
    println!("{}", f1(3))
}
fn main() {
    // test function with no args
    fn t0() -> i32 {
        42
    }
    // test func with 1 arg
    // we're discarding the arg
    // but we need this signature to call test_1_arg
    fn t1(_: i32) -> i32 {
        3
    }
    test_no_args(t0);
    test_1_arg(t1);
    // test_no_args(t1); doesn't compile, test_no_args expects a fn() -> i32
}

注意test_1_arg是如何期望fn(i32)-> i32的,但我们想给它提供我们的t1函数,它并不真正需要输入。

第一个函数意味着我有函数add,但函数本身说我不在乎它是什么。

但是第二个表示我不需要任何参数。它们彼此不兼容。

铁框架需要一个函数,它将提供一个参数给它。框架并不关心你是否使用了参数

相关内容

  • 没有找到相关文章

最新更新