- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有这个枚举类型:
enum Animal {
Dog(i32),
Cat(u8),
}
现在我有一个函数将这种类型作为参数。我知道(出于某种原因)输入始终是 Cat
。我想实现这个:
fn count_legs_of_cat(animal: Animal) -> u8 {
if let Animal::Cat(c) = animal { c } else { unreachable!() }
}
我可以写得更短和/或更地道吗?
最佳答案
我看到的是为每个枚举变体引入一个新的struct
,然后在枚举上使用方法来分解它:
struct Dog(i32);
struct Cat(u8);
enum Animal {
Dog(Dog),
Cat(Cat),
}
impl Animal {
fn cat(self) -> Cat {
if let Animal::Cat(c) = self {
c
} else {
panic!("Not a cat")
}
}
fn dog(self) -> Dog {
if let Animal::Dog(d) = self {
d
} else {
panic!("Not a dog")
}
}
}
// Or better an impl on `Cat` ?
fn count_legs_of_cat(c: Cat) -> u8 {
c.0
}
您不需要结构,因为您可以只返回 u8
,但这可能很难跟踪。如果您有多个具有相同内部类型的变体,那么它可能会产生歧义。
多年来,已经有许多 RFC 对此提供语言支持(最近的一个是 RFC 2593 — Enum variant types )。该提案将允许像 Animal::Cat
这样的枚举变体也成为独立类型,因此您的方法可以直接接受 Animal::Cat
。
我几乎总是喜欢在我固有的实现中编写绝对可靠的代码并迫使调用者 panic :
impl Animal {
fn cat(self) -> Option<Cat> {
if let Animal::Cat(c) = self {
Some(c)
} else {
None
}
}
fn dog(self) -> Option<Dog> {
if let Animal::Dog(d) = self {
Some(d)
} else {
None
}
}
}
我可能会使用匹配
:
impl Animal {
fn cat(self) -> Option<Cat> {
match self {
Animal::Cat(c) => Some(c),
_ => None,
}
}
fn dog(self) -> Option<Dog> {
match self {
Animal::Dog(d) => Some(d),
_ => None,
}
}
}
从 Rust 1.34 开始,我会使用 TryFrom
除了或代替固有实现的特性:
impl TryFrom<Animal> for Cat {
type Error = Animal;
fn try_from(other: Animal) -> Result<Self, Self::Error> {
match other {
Animal::Cat(c) => Ok(c),
a => Err(a),
}
}
}
impl TryFrom<Animal> for Dog {
type Error = Animal;
fn try_from(other: Animal) -> Result<Self, Self::Error> {
match other {
Animal::Dog(d) => Ok(d),
a => Err(a),
}
}
}
考虑使用实现 std::error::Error
的专用错误类型,而不是在失败情况下直接返回 Animal
。您可能还想实现 From
以从 Cat
/Dog
返回到 Animal
。
这一切都会变得乏味,所以宏可能很有用。我敢肯定有很多好的箱子可以做到这一点,但我经常编写自己的一次性解决方案:
macro_rules! enum_thing {
(
enum $Name:ident {
$($Variant:ident($f:ident)),* $(,)?
}
) => {
enum $Name {
$($Variant($Variant),)*
}
$(
struct $Variant($f);
impl TryFrom<$Name> for $Variant {
type Error = $Name;
fn try_from(other: $Name) -> Result<Self, Self::Error> {
match other {
$Name::$Variant(v) => Ok(v),
o => Err(o),
}
}
}
)*
};
}
enum_thing! {
enum Animal {
Dog(i32),
Cat(u8),
}
}
关于enums - 当枚举变体已知时解包内部类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41817718/
这是我的测试用例。 http://tobeythorn.com/isi/dummy2.svg http://tobeythorn.com/isi/isitest.html 如果我自己打开 svg,内部
这是我的测试用例。 http://tobeythorn.com/isi/dummy2.svg http://tobeythorn.com/isi/isitest.html 如果我自己打开 svg,内部
我正在尝试做类似的事情: SELECT SUM( CASE WHEN ( AND EXISTS(SELECT 1
我想问如何在外部 ng-repeat 内部正确使用内部 ng-repeat: 这意味着你想使用这样的东西: {{milestone.id}} {{
我希望在 wordpress 的仪表板内编辑 css 样式并且如果可能的话不必编辑 php 文件。 我知道至少可以编辑一些属性,所以我希望我可以直接在仪表板中编辑所有属性。 更具体地说如何更改自定义类
我在安装在 windows10 上的 vmware 中的 Ubuntu 上安装了伪分布式独立 hadoop 版本。 我从网上下载了一个文件,复制到ubuntu本地目录/lab/data 我在 ubun
我有一个如下所示的 WHERE 语句: WHERE ((@Value1 IS NULL AND [value1_id] IS NULL) OR [value1_id] = ISNULL(@Va
我有一个如下所示的 WHERE 语句: WHERE ((@Value1 IS NULL AND [value1_id] IS NULL) OR [value1_id] = ISNULL(@Va
在我的一些测试帮助程序代码中,我有一个名为 FakeDbSet(Of T) 的 IDbSet(Of T) 实现,它模拟了许多 EF 行为,但没有实际的数据库。我将类声明为 Friend ,因为我想强制
我正在寻找 Cassandra/CQL 的常见 SQL 习语 INSERT INTO ... SELECT ... FROM ... 的表亲。并且一直无法找到任何以编程方式或在 CQL 中执行此类操作
如何防止内部 while 循环无限运行?问题是,如果没有外部 while 循环,内部循环将毫无问题地运行。我知道它必须对外循环执行某些操作,但我无法弄清楚是什么导致了问题。 import java.u
我正在努力学习更多有关 C++ 的知识,但在国际象棋程序中遇到了一些代码,需要帮助才能理解。我有一个 union ,例如: union b_union { Bitboard b; st
这是我项目网页中的代码片段。这里我想显示用户选择的类别,然后想显示属于该类别的主题。在那里,用户可以拥有多个类别,这没有问题。我可以在第一个 while 循环中打印所有这些类别。问题是当我尝试打印主题
我想知道如何在 swing 中显示内部框架。这意味着,当需要 JFrame 时,通常我所做的是, new MyJFrame().setVisible(true); 假设之前的表单也应该显示。当显示这个
我最近发现了一些有趣的行为,这让我想知道对象如何知道存在哪些全局变量。例如,假设我有一个文件“test.py”: globalVar = 1 toDelete = 2 class Test(objec
我知道它已经在这里得到回答: google maps drag and drop objects into google maps from outside the Map ,但这并不完全是我所需要的
我目前正在学习Javascript DOM和innerHTML,发现在理解innerHTML方面存在一些问题。 这是我的代码:http://jsfiddle.net/hphchan/bfjx1w70/
我构建了一个布局如下的库: lib/ private_class_impl.cc private_class_decl.h public_class_impl.cc include/
我有一个使用 bootstrap 3 的组合 wordpress 网站。它基本上是一个图像网格。当屏幕展开时,它会从三列变为四列。移动时它是一列。 我想出了如何调整图像的顶部和底部边距,但我希望图像的
我正在试用 MSP-EXP430G2 的教程程序,使用 Code Composer Studio 使 LED 闪烁。最初,它有一个闪烁的无限循环: for(;;) // This emp
我是一名优秀的程序员,十分优秀!