@@ -242,7 +242,8 @@ \subsection{二元运算符}\label{biop}
242242\subsection {复合赋值运算符 }\label {assign }
243243复合赋值运算符例如\texttt {x += y }或\texttt {x \& = y }需要两个参数,然后对它们进行一些操作例如加法或位与,最后把结果保存到左侧的操作数。在Rust中,复合赋值表达式的值总是\texttt {() },而不是最后被存储的值。
244244
245- 很多语言都有这些运算符,并通常把它们定义为像\texttt {x = x + y }或\texttt {x = x \& y }这样的表达式的缩写。然而,Rust并没有采用这种方案。作为代替,\texttt {x += y }是方法调用\texttt {x.add\_ assign(y) }的缩写,而\texttt {add\_ assign }是\texttt {std::ops::AddAssign } trait唯一的方法:
245+ 很多语言都有这些运算符,并通常把它们定义为像\texttt {x = x + y }或\texttt {x = x \& y }这样的表达式的缩写。然而,Rust并没有采用这种方案。作为代替,\texttt {x += y }是方法调用\texttt {x.add\_ assign(y) }的缩写,而\texttt {add\_ assign }是\\
246+ \texttt {std::ops::AddAssign } trait唯一的方法:
246247\begin {minted }{Rust}
247248 trait AddAssign<Rhs = Self> {
248249 fn add_assign(&mut self, rhs: Rhs);
@@ -357,7 +358,8 @@ \section{相等性比较}\label{equal}
357358 Rhs: ?Sized,
358359\end {minted }
359360
360- 这放松了Rust通常要求类型参数必须是固定大小类型的要求,所以我们才可以写\texttt {PartialEq<str> }或\texttt {PartialEq<[T]> }这样的trait。\texttt {eq }和\texttt {ne }方法以类型\texttt {\& Rhs }获取参数,并用\texttt {\& str }或者\texttt {\& [T] }来进行比较是完全合理的。因为\texttt {str }实现了\texttt {PartialEq<str> },所以下面的断言是等价的:
361+ 这放松了Rust通常要求类型参数必须是固定大小类型的要求,所以我们才可以写\texttt {PartialEq<str> }或\\
362+ \texttt {PartialEq<[T]> }这样的trait。\texttt {eq }和\texttt {ne }方法以类型\texttt {\& Rhs }获取参数,并用\texttt {\& str }或者\texttt {\& [T] }来进行比较是完全合理的。因为\texttt {str }实现了\texttt {PartialEq<str> },所以下面的断言是等价的:
361363\begin {minted }{Rust}
362364 assert!("ungula" != "ungulate" );
363365 assert!("ungula".ne("ungulate"));
@@ -372,7 +374,8 @@ \section{相等性比较}\label{equal}
372374 \item \texttt {x == x }必须总是为真。
373375\end {itemize }
374376
375- 最后一个要求看起来似乎太明显以至于不值得列出来,但这正是导致事情变得复杂的地方。Rust的\texttt {f32 }和\texttt {f64 }是IEEE标准的浮点数类型。根据这个标准,像\texttt {0.0/0.0 }以及其他没有合适的结果的表达式必须产生一个特殊的\emph {非数(not-a-number) }值,通常被称为NaN值。标准还要求一个NaN值必须和其他任何值都不想等——包括它自己。例如,这个标准要求以下行为:
377+ 最后一个要求看起来似乎太明显以至于不值得列出来,但这正是导致事情变得复杂的地方。Rust的\texttt {f32 }和\texttt {f64 }\\
378+ 是IEEE标准的浮点数类型。根据这个标准,像\texttt {0.0/0.0 }以及其他没有合适的结果的表达式必须产生一个特殊的\emph {非数(not-a-number) }值,通常被称为NaN值。标准还要求一个NaN值必须和其他任何值都不想等——包括它自己。例如,这个标准要求以下行为:
376379\begin {minted }{Rust}
377380 assert!(f64::is_nan(0.0 / 0.0));
378381 assert_eq!(0.0 / 0.0 == 0.0 / 0.0, false);
@@ -434,7 +437,8 @@ \section{顺序性比较}\label{cmp}
434437
435438注意\texttt {PartialOrd<Rhs> }扩展了\texttt {PartialEq<Rhs> }:你只能对可以比较相等性的类型比较顺序性。
436439
437- 你唯一需要实现的\texttt {PartialOrd }的方法就是\texttt {partial\_ cmp }。当\texttt {partial\_ cmp }返回\texttt {Some(o) }时,\texttt {o }表示\texttt {self }和\texttt {other }的关系:
440+ 你唯一需要实现的\texttt {PartialOrd }的方法就是\texttt {partial\_ cmp }。当\texttt {partial\_ cmp }返回\texttt {Some(o) }时,\texttt {o }表示\texttt {self }和\\
441+ \texttt {other }的关系:
438442\begin {minted }{Rust}
439443 enum Ordering {
440444 Less, // self < other
@@ -522,15 +526,17 @@ \section{顺序性比较}\label{cmp}
522526 intervals.sort_by_key(|i| i.upper);
523527\end {minted }
524528
525- 实现\texttt {Ord }的类型还可以使用\texttt {Reverse }包装类型来反转顺序。对于任何实现了\texttt {Ord }的类型\texttt {T },\texttt {std::cmp::Reverse<T> }也会自动实现\texttt {Ord },但是是以相反的顺序。例如,将我们的区间按照下界降序排列会很简单:
529+ 实现\texttt {Ord }的类型还可以使用\texttt {Reverse }包装类型来反转顺序。对于任何实现了\texttt {Ord }的类型\texttt {T },\\
530+ \texttt {std::cmp::Reverse<T> }也会自动实现\texttt {Ord },但是是以相反的顺序。例如,将我们的区间按照下界降序排列会很简单:
526531\begin {minted }{Rust}
527532 use std::cmp::Reverse;
528533 intervals.sort_by_key(|i| Reverse(i.lower));
529534\end {minted }
530535
531536\section {\texttt {Index }与\texttt {IndexMut } }\label {index }
532537
533- 你可以通过为你的类型实现\texttt {std::ops::Index }和\texttt {std::ops::IndexMut } trait来指明索引表达式例如\texttt {a[i] }的行为。数组直接支持\texttt {[] }运算符,但对于任何其他类型,表达式\texttt {a[i] }通常是\texttt {*a.index(i) }的缩写,其中\texttt {index }是\texttt {std::ops::Index } trait的一个方法。然而,如果表达式被赋值或者可变借用,那么将是\texttt {*a.index\_ mut(i) }的缩写,它是\texttt {std::ops::IndexMut } trait的一个方法。
538+ 你可以通过为你的类型实现\texttt {std::ops::Index }和\texttt {std::ops::IndexMut } trait来指明索引表达式例如\texttt {a[i] }的行为。数组直接支持\texttt {[] }运算符,但对于任何其他类型,表达式\texttt {a[i] }通常是\texttt {*a.index(i) }的缩写,其中\texttt {index }是\\
539+ \texttt {std::ops::Index } trait的一个方法。然而,如果表达式被赋值或者可变借用,那么将是\texttt {*a.index\_ mut(i) }的缩写,它是\texttt {std::ops::IndexMut } trait的一个方法。
534540
535541这是这两个trait的定义:
536542\begin {minted }{Rust}
@@ -639,4 +645,10 @@ \section{\texttt{Index}与\texttt{IndexMut}}\label{index}
639645
640646注意当我们写\texttt {image[row][column] }时,如果\texttt {row }越界了,我们的\texttt {.index() }方法会尝试索引越界的\texttt {self.pixels },触发一个panic。这是\texttt {Index }和\texttt {IndexMut }的实现应有的行为:越界访问将被检测到并触发一个panic,当你索引一个越界的数组、切片或vector时也是这样。
641647
642- \section {}
648+ \section {其他运算符 }
649+
650+ Rust中并不是所有运算符都可以被重载。在Rust 1.50中,错误检查的\texttt {? }运算符只能用于\texttt {Result }和\texttt {Option }值,尽管有工作正在将其扩展到用户自定义的类型。 类似的,逻辑运算符\texttt {\&\& }和\texttt {|| }只能用于布尔值。\texttt {.. }和\texttt {..= }运算符总是创建一个表示范围的约束的结构体、\texttt {\& }运算符总是借用引用、\texttt {= }运算符总是移动或者拷贝值。它们都不能被重载。
651+
652+ 解引用运算符\texttt {*val }以及访问字段和方法的点运算符\texttt {val.field }和\texttt {val.method() }可以使用“\nameref {deref }” trait来重载,我们将在下一节介绍它。(我们没有在这里介绍是因为这些trait不仅仅只是重载一些运算符。)
653+
654+ Rust不支持重载函数调用运算符\texttt {f(x) }。作为代替,当你需要一个可调用的值时,你通常只需要写一个闭包。我们将在\hyperref [ch14]{第14章}中解释这是怎么工作的,并介绍特殊的\texttt {Fn }、\texttt {FnMut }和\texttt {FnOnce } trait。
0 commit comments