普段C++書いていて今回Rustに挑戦しています。
rust
1struct TypeElement<'a> { 2 before: Option<&'a str>, 3 after: Option<&'a str>, 4 value: Option<&'a str>, 5}
のようなstructに対してPartialEq
を実装しようとしています。
value
が双方値を持つなら値の比較結果- (
before
が双方値を持つならその値の比較結果) かつ (after
が双方値を持つなら値の比較結果、双方持たないなら真) - その他は偽
という条件を書こうとした結果、match
がネストしすぎた地獄を産んでしまいました。
rust
1impl<'a> PartialEq<TypeElement<'a>> for TypeElement<'a> { 2 fn eq<'b>(&self, other: &TypeElement<'b>) -> bool { 3 match self.value { 4 Some(l) => { 5 match other.value { 6 // check `value` 7 Some(r) => l.eq(r), 8 None => false, 9 } 10 }, 11 None => { 12 match other.value { 13 Some(_) => false, 14 // check `before`, `after` 15 None => { 16 match self.before { 17 Some(b1) => { 18 match other.before { 19 Some(b2) => { 20 b1.eq(b2) && match self.after { 21 Some(a1) => { 22 match other.after { 23 Some(a2) => a1.eq(a2), 24 None => false, 25 } 26 }, 27 None => { 28 match other.after { 29 Some(_) => false, 30 None => true, 31 } 32 }, 33 } 34 } 35 None => false 36 } 37 }, 38 None => false, 39 } 40 }, 41 } 42 }, 43 } 44 } 45}
C++17のstd::optional
はoperator==
があるのですが、Rustにはそれに該当するものを見つけられませんでした。
もうすこし可読性のある書き方をするにはどうしたらいいでしょうか?
追記
gyu-donさんの回答を受けて
rust
1impl<'a> PartialEq<TypeElement<'a>> for TypeElement<'a> { 2 fn eq<'b>(&self, other: &TypeElement<'b>) -> bool { 3 if self.value.is_some() { 4 self.value == other.value 5 } else { 6 self.before.is_some() && self.before == other.before && self.after == other.after 7 } 8 } 9}
のように書き換えたのですが、8e6aa6f
> cargo test Compiling cpp_template_type_indenter_lib v0.1.0 (file:///C:/Users/yumetodo/Documents/rust/cpp_template_type_indenter_lib) error[E0308]: mismatched types --> src\type_element.rs:19:83 | 19 | self.before.is_some() && self.before == other.before && self.after == other.after | ^^^^^^^^^^^ lifetime mismatch | = note: expected type `std::option::Option<&'a str>` found type `std::option::Option<&'b str>` note: the lifetime 'b as defined on the method body at 15:5... --> src\type_element.rs:15:5 | 15 | / fn eq<'b>(&self, other: &TypeElement<'b>) -> bool { 16 | | if self.value.is_some() { 17 | | self.value == other.value 18 | | } else { 19 | | self.before.is_some() && self.before == other.before && self.after == other.after 20 | | } 21 | | } | |_____^ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 14:1 --> src\type_element.rs:14:1 | 14 | / impl<'a> PartialEq<TypeElement<'a>> for TypeElement<'a> { 15 | | fn eq<'b>(&self, other: &TypeElement<'b>) -> bool { 16 | | if self.value.is_some() { 17 | | self.value == other.value ... | 21 | | } 22 | | } | |_^ error: aborting due to previous error(s) error[E0308]: mismatched types --> src\type_element.rs:19:83 | 19 | self.before.is_some() && self.before == other.before && self.after == other.after | ^^^^^^^^^^^ lifetime mismatch | = note: expected type `std::option::Option<&'a str>` found type `std::option::Option<&'b str>` note: the lifetime 'b as defined on the method body at 15:5... --> src\type_element.rs:15:5 | 15 | / fn eq<'b>(&self, other: &TypeElement<'b>) -> bool { 16 | | if self.value.is_some() { 17 | | self.value == other.value 18 | | } else { 19 | | self.before.is_some() && self.before == other.before && self.after == other.after 20 | | } 21 | | } | |_____^ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 14:1 --> src\type_element.rs:14:1 | 14 error:| /Could not compile `cpp_template_type_indenter_lib`. impl<'a> PartialEq<TypeElement<'a>> for TypeElement<'a> { 15Build failed, waiting for other jobs to finish... | | fn eq<'b>(&self, other: &TypeElement<'b>) -> bool { 16 | | if self.value.is_some() { 17 | | self.value == other.value ... | 21 | | } 22 | | } | |_^ error: aborting due to previous error(s) error: Could not compile `cpp_template_type_indenter_lib`. To learn more, run the command again with --verbose.
のように怒られます。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/12/11 09:18
2017/12/11 09:43
2017/12/11 11:01
2017/12/11 14:20