我想指示Rust编译器在任何情况下都不求值。这是一个示例:
#![allow(dead_code)]
trait CheckTrait {
fn check(b : bool);
}
struct CheckStructA {}
struct CheckStructB {}
impl CheckTrait for CheckStructA {
fn check(_b : bool) {
println!("CheckStructA");
}
}
impl CheckTrait for CheckStructB {
// compiler: do not evaluate the argument _b
fn check(_b : bool) {
}
}
fn show_stuff_a() -> bool {
println!("Show stuff A");
true
}
fn show_stuff_b() -> bool {
println!("Show stuff B");
true
}
fn test_a<T : CheckTrait>(_ : T) {
T::check(show_stuff_a());
}
fn test_b<T : CheckTrait>(_ : T) {
T::check(show_stuff_b());
}
fn main() {
test_a(CheckStructA{});
test_b(CheckStructB{});
}
这里CheckStructB
实际上是CheckStructA
的禁用版本。在注释的地方,我希望能够指示编译器不要为_b
计算任何表达式可以计算CheckStructB::check
,但仍可以为{{1} }。此代码的结果是,它将仍然向控制台输出“ Show Stuff A”,但不会向控制台输出“ Show Stuff B”。
在C#中,可以通过将注释替换为[System.Diagnostics.Conditional(“ DoNotEverTurnThisOn”)]来完成。我不想在宏中定义类型,因为这会破坏智能感知。
我如何在Rust中做到这一点?
答案 0 :(得分:6)
仅在必要时评估参数称为“懒惰评估”。
在像Haskell这样的语言(默认为“惰性评估”)中,类型bool
的参数或变量实际上不会立即表示为bool
,而是表示为“ thunk”,包含要调用的函数及其自己的参数(可能是重击)。
在Rust中,由于默认设置是Eager Evaluation,因此您需要以参数类型或有价值的类型显式表示惰性。通常,这不是通过要求T
,而是要求FnOnce() -> T
来完成的。
因此,您将check
重写为:
fn check<F: FnOnce() -> bool>(condition: F);
然后,由实现决定是否评估F
,如果没有评估,则什么也不执行。
注意:如果您不希望使用泛型check
,则可以将Box<FnOnce() -> bool>
作为参数;但是,它将需要堆分配...就像在Haskell中一样。
让我们看看一些代码! Playground link
trait CheckTrait {
fn check<F: FnOnce() -> bool>(b: F);
}
struct CheckStructA {}
struct CheckStructB {}
impl CheckTrait for CheckStructA {
fn check<F: FnOnce() -> bool>(b: F) {
b();
println!("CheckStructA");
}
}
impl CheckTrait for CheckStructB {
fn check<F: FnOnce() -> bool>(_b: F) {
println!("CheckStructB");
}
}
fn show_stuff_a() -> bool {
println!("Show stuff A");
true
}
fn show_stuff_b() -> bool {
println!("Show stuff B");
true
}
fn test_a<T : CheckTrait>(_ : T) {
T::check(|| show_stuff_a());
}
fn test_b<T : CheckTrait>(_ : T) {
T::check(|| show_stuff_b());
}
fn main() {
test_a(CheckStructA{});
test_b(CheckStructB{});
}