我正在使用Serde JSON板条箱将JSON文件反序列化为结构,并且其中一个属性是可选的。当属性缺少默认值(从命令行)时,它将被替换。这导致我修改代码,从而引发以下错误,并且很难弄清楚如何解决它。
我的问题是,除非将值分配给临时变量,否则我将得到type ascription is experimental error
,但我不明白为什么。我将展示代码,并忽略Config
的结构,因为我认为这并不重要。
这是有效的代码:
pub fn new(file_name: &str, param_urls: &[String]) -> Result<Config, io::Error> {
let mut config: Config = Config {
queue: None
};
if Path::new(file_name).exists() {
let json = read_to_string(file_name)?;
let c: Config = serde_json::from_str(&json)?;
config = c;
// ^^^^^^^ must use temporary c variable
}
if config.queue.is_none() {
config.queue = Some(param_urls.to_vec());
}
Ok(Config {
queue: None
})
}
上面的代码花了我一段时间,我不明白为什么它可以解决错误,但是这里是引发错误的原始源代码。
pub fn new(file_name: &str, param_urls: &[String]) -> Result<Config, io::Error> {
let mut config: Config = Config {
queue: None
};
if Path::new(file_name).exists() {
let json = read_to_string(file_name)?;
config: Config = serde_json::from_str(&json)?;
// ^^^^^^^^^^^ ERROR! type ascription is experimental error
}
if config.queue.is_none() {
config.queue = Some(param_urls.to_vec());
}
Ok(Config {
queue: None
})
}
作为来自其他语言的新Rust程序员。我根本不理解此错误,并且在没有任何明确解释的情况下对Google进行了搜索。从我的角度来看,我来自其他语言,在这里看不到任何区别,也不了解解决了什么问题或原因。
答案 0 :(得分:3)
要将我的评论扩展为答案,请在使用冒号显式表示变量的类型时键入归因。这样的示例已经存在于您的代码中:config: Config
,这意味着config
的类型为Config
。大多数时候,Rust能够根据变量的值推断出变量的类型,因此不需要类型说明。实际上,除少数特殊情况外,该语言甚至还不允许输入类型说明(请参见this issue)。
现在允许类型归类的主要地方是在声明变量时。这是当您说诸如let x: u32 = 7;
或let mut s: String = "abc".to_string();
之类的内容时。同样,在定义结构时,可以使用type ascription来描述其字段:
struct Foo {
bar: Vec<i32>,
baz: String,
}
可以(或必须)使用类型说明的另一个主要地方是在函数和闭包参数中。例如
fn add_one(x: u64) -> u64 {
x + 1
}
或let f = |t: String| t + "123"
。使用闭包时,通常可以根据闭包的使用方式来推断变量的类型,但有时对编译器或读者明确声明参数的类型很有帮助。
在您的特定情况下,您将类型归因用于重新分配操作,该操作目前不属于允许类型归因的任何类别。 config: Config = serde_json::from_str(&json)?;
可以毫无问题地更改为config = serde_json::from_str(&json)?;
,因为编译器已经知道config
的类型为Config
。重新分配很少需要类型归属,因为它不能更改变量的类型。