【问题标题】:How can I use std::convert::Into to convert something that might fail?如何使用 std::convert::Into 转换可能失败的内容?
【发布时间】:2015-05-21 01:43:28
【问题描述】:

我想要一个函数,它接受可以转换为我的特定类型的各种类型。在类似的情况下,我会使用std::convert::Into(或std::convert::From):

pub struct MyThing;

impl<'a> Into<MyThing> for &'a str {
    fn into(self) -> MyThing { 
        MyThing
    }
}

fn main() {}

作为一个额外的问题,在我的具体情况下,转换可能会失败。通常,我会使用Result 来表示可能失败的操作。将两个概念结合在一起:

pub struct MyThing;
pub struct Error;

impl<'a> Into<Result<MyThing, Error>> for &'a str {
    fn into(self) -> Result<MyThing, Error> { 
        if self.len() % 2 == 0 {
            Ok(MyThing)
        } else {
            Err(Error)
        }
    }
}

fn main() {}

不幸的是,这似乎违反了连贯性规则:

error: the impl does not reference any types defined in this crate;
only traits defined in the current crate can be implemented for
arbitrary types [E0117]

我发现我可以创建自己的特定特征:

struct MyThing;
struct Error;

trait IntoMyThing {
    fn into(self) -> Result<MyThing, Error>;
}

impl<'a> IntoMyThing for &'a str {
    fn into(self) -> Result<MyThing, Error> { 
        if self.len() % 2 == 0 {
            Ok(MyThing)
        } else {
            Err(Error)
        }
    }
}

fn main() {}

甚至是更通用的特征:

struct MyThing;
struct Error;

trait MaybeInto<T, E> {
    fn into(self) -> Result<T, E>;
}

impl<'a> MaybeInto<MyThing, Error> for &'a str {
    fn into(self) -> Result<MyThing, Error> { 
        if self.len() % 2 == 0 {
            Ok(MyThing)
        } else {
            Err(Error)
        }
    }
}

fn main() {}

但是有没有办法重用标准库中的组件来实现我的目标?

【问题讨论】:

    标签: rust


    【解决方案1】:

    由于连贯性规则,这是不可能的,这使得这样的事情非常不方便,因为除非您为其中一种类型(Result 或 @)创建新类型,否则您无法做到这一点987654323@。请参阅RFC #1023 了解更多信息。

    简而言之,根据该 RFC 规定的新规则,您不能为非本地的类型实现非本地的特征。

    1. 修改孤儿规则,以便远程 trait 的 impls 需要本地类型,即当前 crate LT = LocalTypeConstructor&lt;...&gt; 中定义的 struct/enum/trait 或对本地类型 LT = ... | &amp;LT | &amp;mut LT 的引用。

    因此,由于您没有在 crate 中创建 Into 特征,也没有创建 Result 类型,因此您会收到此错误。创建一个新类型可以解决这个问题,因为它基本上将非本地类型包装在本地类型中。

    【讨论】:

    • 哎呀!那个 RFC 是一头野兽,老实说,我从中得到的唯一东西(与这个问题有关)是你不能为不属于你的类型定义一个不属于你的特性(特性的本地)。
    • 我是唯一一个觉得以“nah”开头的答案有点居高临下,或者至少有点过于非正式的人,无论其内容多么正确?我也承认我对此感觉更强烈,因为@shepmaster 更经常地帮助我,我可以指望最高质量的答案,保持他们的风格中立,防止自己因为提问而感到愚蠢。
    • 这很容易解决,无需指责我居高临下,尤其是当我的帮助意图(以及我的回答历史)表明我不是那样的时候。我错误地随意地开始了我的回答,在这种情况下,“不”是为了传达一种哀悼的感觉,例如,“不,这是不可能的,这很遗憾。”连贯性(这个问题的主题)是 Rust 中这种感觉的来源。我看不出我的回答给人的印象是我在居高临下,或者试图让 Shep 觉得问这个问题很愚蠢。
    • 豪尔赫·伊斯雷尔·佩尼亚 — 不用担心。我知道有时最好在外面添加一个快速的答案来让人们滚动。我主要希望您添加更多散文,以使答案更好地经受住时间的考验。 @Byron 的感觉仍然有效,如果有其他人也有类似的感觉,我也不会感到惊讶。这对我们所有人来说都是一件好事!
    • 请注意,我的评论是为了不指责任何人而写的,这只是一个要求反馈的问题,因为错误很可能站在我这边。此后,答案已经被编辑,并且在我看来,达到了我从 SO 中所知道的质量。尽管没有说出来,但我高度重视 Jorge 的工作,毫无疑问,他是这个社区中备受赞誉的成员。
    猜你喜欢
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    相关资源
    最近更新 更多