Skip to content

Commit 83788b9

Browse files
committed
完成了第12章
1 parent 13ebdba commit 83788b9

2 files changed

Lines changed: 27 additions & 7 deletions

File tree

src/ch12.tex

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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。

src/ch13.tex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
\chapter{工具trait}\label{ch13}
22

3+
\emph{Science is nothing else than the search to discover unity in the wild variety of nature—or, more exactly, in the variety of our experience. Poetry, painting, the arts are the same search, in Coleridge’s phrase, for unity in variety.}
4+
5+
\begin{flushright}
6+
——Jacob Bronowski
7+
\end{flushright}
8+
9+
这一章将介绍介绍
10+
311
\section{\texttt{Sized}}\label{sized}
412

513
\section{\texttt{Drop}}\label{drop}

0 commit comments

Comments
 (0)