This question already has answers here:
Expected closure, found a different closure
(2个答案)
What is the inferred type of a vector of closures?
(1个答案)
2年前关闭。
我正在尝试构建一个简单的RPN计算器,并且已经具备一些基本功能。我想制作一个dispatch table来实现各种计算器功能。如果我在Perl中执行此操作,则将编写类似以下内容的内容:
或在JavaScript中:
到目前为止,这是我在Rust中尝试过的方法:
当我尝试编译时,出现以下错误:
“没有两个闭包,即使相同,也没有相同的类型”是什么意思?我怎样才能使HashMap持有一个闭包,然后调用它?
听起来使用
现在,您需要哈希表的显式类型。就编译器而言,您定义的两个闭包是完全不同的类型。但是,它们均与
最后,
完整示例
请注意,您可以将
(2个答案)
What is the inferred type of a vector of closures?
(1个答案)
2年前关闭。
我正在尝试构建一个简单的RPN计算器,并且已经具备一些基本功能。我想制作一个dispatch table来实现各种计算器功能。如果我在Perl中执行此操作,则将编写类似以下内容的内容:
my %ops = (
'+' => sub { +shift + +shift; },
'-' => sub { +shift - +shift; },
'*' => sub { +shift * +shift; },
'/' => sub { +shift / +shift; }
);
或在JavaScript中:
let ops = {
"+": (a, b) => a + b,
"-": (a, b) => a - b,
"*": (a, b) => a * b,
"/": (a, b) => a / b
};
到目前为止,这是我在Rust中尝试过的方法:
use std::collections::HashMap;
fn main() {
println!("Going to call +");
let dispatch = HashMap::new();
dispatch.insert(String::from("+"), |a, b| a + b);
dispatch.insert(String::from("-"), |a, b| a - b);
let plus = dispatch.get(&String::from("+"));
println!("2 + 3 = {}", plus(2, 3));
let minus = dispatch.get(&String::from("-"));
println!("2 - 3 = {}", minus(2, 3));
}
当我尝试编译时,出现以下错误:
error[E0308]: mismatched types
--> src/main.rs:9:40
|
9 | dispatch.insert(String::from("-"), |a, b| a - b);
| ^^^^^^^^^^^^ expected closure, found a different closure
|
= note: expected type `[closure@src/main.rs:8:40: 8:52]`
found type `[closure@src/main.rs:9:40: 9:52]`
= note: no two closures, even if identical, have the same type
= help: consider boxing your closure and/or using it as a trait object
error[E0618]: expected function, found enum variant `plus`
--> src/main.rs:12:28
|
11 | let plus = dispatch.get(&String::from("+"));
| ---- `plus` defined here
12 | println!("2 + 3 = {}", plus(2, 3));
| ^^^^^^^^^^ not a function
help: `plus` is a unit variant, you need to write it without the parenthesis
|
12 | println!("2 + 3 = {}", plus);
| ^^^^
error[E0618]: expected function, found enum variant `minus`
--> src/main.rs:15:28
|
14 | let minus = dispatch.get(&String::from("-"));
| ----- `minus` defined here
15 | println!("2 - 3 = {}", minus(2, 3));
| ^^^^^^^^^^^ not a function
help: `minus` is a unit variant, you need to write it without the parenthesis
|
15 | println!("2 - 3 = {}", minus);
| ^^^^^
“没有两个闭包,即使相同,也没有相同的类型”是什么意思?我怎样才能使HashMap持有一个闭包,然后调用它?
听起来使用
Box
可以解决此问题...就像我说的那样,我很新,而且我还没有使用Box
。我如何开箱即用? 最佳答案
这里有一些正交的问题。首先,您的哈希图是不可变的。您可以使用let
而不是let mut
,这是一个好习惯,但是为了能够插入其中,我们需要(至少在最初是)let mut
。如果您打算在初始构造后修改哈希图,则可能还需要对let mut
变量进行dispatch
编码。
let dispatch = {
let mut temp = HashMap::new();
temp.insert(String::from("+"), |a, b| a + b);
temp.insert(String::from("-"), |a, b| a - b);
temp
};
现在,您需要哈希表的显式类型。就编译器而言,您定义的两个闭包是完全不同的类型。但是,它们均与
fn(i32, i32) -> i32
上的二进制函数类型i32
兼容(如果需要,您可以将i32
替换为其他数值类型),因此让我们将类型明确。let dispatch = {
let mut temp: HashMap<String, fn(i32, i32) -> i32> = HashMap::new();
temp.insert(String::from("+"), |a, b| a + b);
temp.insert(String::from("-"), |a, b| a - b);
temp
};
最后,
HashMap.get
返回的是 std::option::Option
,而不是直接值,因此我们需要对其进行拆包。如果找不到 key ,则get
返回None
。如果这是一个很大的项目,我们可以适当地处理该错误,也许可以通过记录错误或告诉用户来解决,但对于像这样的简单事情,我们只需要使用expect
即可,它实际上告诉编译器“是的,我知道这可以出了头大错。我故意不理会这个事实。”对于我们的简单示例而言,这是完全可以的。let plus = dispatch.get(&String::from("+")).expect("Couldn't find +");
let minus = dispatch.get(&String::from("-")).expect("Couldn't find -");
完整示例
use std::collections::HashMap;
fn main() {
let dispatch = {
let mut temp: HashMap<String, fn(i32, i32) -> i32> = HashMap::new();
temp.insert("+".into(), |a, b| a + b);
temp.insert("-".into(), |a, b| a - b);
temp
};
let plus = dispatch["+"];
println!("2 + 3 = {}", plus(2, 3));
let minus = dispatch["-"];
println!("2 - 3 = {}", minus(2, 3));
}
请注意,您可以将
String
替换为&'static str
:let dispatch = {
let mut temp: HashMap<_, fn(i32, i32) -> i32> = HashMap::new();
temp.insert("+", |a, b| a + b);
temp.insert("-", |a, b| a - b);
temp
};
关于rust - 如何在Rust中制作分派(dispatch)表? [复制],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51372702/
10-10 04:54