当没有类型参数或归属时,如何暗示值的类型? [英] How do I imply the type of the value when there are no type parameters or ascriptions?

查看:37
本文介绍了当没有类型参数或归属时,如何暗示值的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将我的结构转换为 HashMap,但是在 impl 块中时我无法这样做.由于板条箱约束,我只能使用&self 作为 resolve 函数的参数.

I am trying to convert my struct into a HashMap, but I am unable to do so while being in the impl block. Due to a crate constraint, I can only use &self as a parameter for the resolve function.

use std::collections::HashMap;

pub enum Value {
    Int(i64),
    Object(HashMap<String, Value>),
}

pub struct WeatherSettings {
    forecast_days: i64,
}

impl WeatherSettings {
    fn resolve(&self) -> Value {
        let json_object: HashMap<String, Value> = *self.into();
        Value::Object(json_object)
    }
}

impl From<WeatherSettings> for HashMap<String, Value> {
    fn from(weather: WeatherSettings) -> HashMap<String, Value> {
        let mut json_object = HashMap::new();
        json_object.insert("forecast_days".to_owned(),
                           Value::Int(weather.forecast_days));
        return json_object;
    }
}

fn main() {}

更直接,我得到错误:

error: the type of this value must be known in this context
  --> src/main.rs:14:51
   |
14 |         let json_object: HashMap<String, Value> = *self.into();
   |                                                   ^^^^^^^^^^^^

推荐答案

当没有类型参数或归属时,如何暗示值的类型?

How do I imply the type of the value when there is no type parameters or ascriptions?

在绝大多数情况下,Rust 编译器可以根据泛型类型的值的使用方式来推断类型或函数的泛型类型.

In the vast majority of cases, the Rust compiler can infer the generic types of a type or function based on how values of the generic type are used.

在某些情况下,没有足够的信息来推断泛型类型的确切类型,但总有一种方法可以在类型参数存在时传递它们.

In some cases, there isn't enough information to infer exactly one type for a generic type, but there is always a way to pass type parameters when they exist.

这样做的两种方法是使用 turbofish完全限定语法呼叫站点.

The two ways of doing so are to use the turbofish or fully qualified syntax at the call site.

turbofish 是附加到函数或类型的符号 ::<Type1, Type2, ...>.看看它看起来像一条鱼吗?

The turbofish is the symbols ::<Type1, Type2, ...> appended to a function or type. See how it looks like a fish?

mem::size_of 定义为:

pub const fn size_of<T>() -> usize.

您可以将其称为:

std::mem::size_of::<i8>()
//               ^^^^^^ turbofish

类型示例

Vec::new定义为:

impl<T> Vec<T> {
    pub fn new() -> Vec<T>
}

您可以将其称为:

Vec::<u8>::new()
// ^^^^^^ turbofish

多种类型

如果你的函数有多种类型,你需要按照定义的顺序为每种类型指定一些东西:

Multiple types

If your function has multiple types, you need to specify something for each type in the same order as the definition:

fn example<A, B>() {}

fn main() {
    example::<i32, bool>();
    //         ^A  ^B
}

完全限定的语法

如果您需要使用类型参数消除对特定特征的方法调用的歧义,您可以使用完全限定的语法.

Fully qualified syntax

If you need to disambiguate a method call to a specific trait with a type parameter, you can use the fully qualified syntax.

From::from定义为:

trait From<T> {
    fn from(T) -> Self;
}

您可以将其称为:

    <String as From<&str>>::from("a")
//  ^^^^^^^^^^^^^^^^^^^^^^ fully qualified syntax

部分推断类型

如果可以提供多种类型,但其中一些可以推断,您仍然可以使用 _ 来允许编译器推断该特定类型.

Partially inferring types

If there are multiple types that can be provided but some of them can be inferred, you can still use _ to allow the compiler to infer that specific type.

这里,我使用 Into 类型上的 turbofish 为您的代码:

Here, I use the turbofish on the Into type for your code:

let json_object = *Into::<HashMap<String, Value>>::into(self);

不过那不是你的问题.

为了使这一行有效:

let json_object: HashMap<String, Value> = *self.into();

调用 self.into() 的结果必须是可以取消引用以产生 HashMap 类型的东西.编译器如何知道那是什么?这也不是你想要的.

The result of the call to self.into() must be something that could be dereferenced to produce the type HashMap<String, Value>. How is the compiler expected to know what that is? It's also not what you want.

你所拥有的只是&self,所以这就是你必须转换的.实现 trait 以引用您的结构:

All you have is &self, so that's what you have to convert from. Implement the trait for a reference to your struct:

impl<'a> From<&'a WeatherSettings> for HashMap<String, Value> {
    fn from(weather: &'a WeatherSettings) -> HashMap<String, Value> {
        let mut json_object = HashMap::new();
        json_object.insert("unit".to_owned(), Value::String(weather.unit.clone()));
        json_object.insert("forecast_days".to_owned(), Value::Int(weather.forecast_days));
        json_object.insert("data".to_owned(), Value::String(weather.data.clone()));
        json_object
    }
}

这意味着您不能移动字符串,而必须复制它们.这是 &self 的限制.

This means you cannot move the strings over, but instead have to copy them. That's the restriction placed by the &self.

这篇关于当没有类型参数或归属时,如何暗示值的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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