Skip to content

Commit 9def5fa

Browse files
authored
Merge pull request #2823 from benluo/zh-cn/overviews/scala3-book/ca-context-bounds
2 parents 53b9b52 + a28ad15 commit 9def5fa

File tree

1 file changed

+76
-16
lines changed

1 file changed

+76
-16
lines changed

_zh-cn/overviews/scala3-book/ca-context-bounds.md

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,101 @@ permalink: "/zh-cn/scala3/book/:title.html"
1414
---
1515

1616

17-
{% comment %}
18-
- TODO: define "context parameter"
19-
- TODO: define "synthesized" and "synthesized arguments"
20-
{% endcomment %}
21-
22-
23-
在许多情况下,_上下文参数_的名称不必明确提及,因为它仅由编译器在其他上下文参数的合成参数中使用。
17+
在许多情况下,[上下文参数]({% link _overviews/scala3-book/ca-context-parameters.md %}#context-parameters) 的名称不必显式提及,因为它仅在编译器为其他上下文参数合成实参的时候用到。
2418
在这种情况下,您不必定义参数名称,只需提供参数类型即可。
2519

2620
## 背景
2721

28-
例如,这个 `maximum` 方法接受 `Ord` 类型的_上下文参数_,只是将它作为参数传递给 `max`
22+
例如,假设一个 `maxElement` 方法返回一个集合里的最大值
2923

24+
{% tabs context-bounds-max-named-param class=tabs-scala-version %}
25+
{% tab 'Scala 2' %}
3026
```scala
31-
def maximum[A](xs: List[A])(using ord: Ord[A]): A =
32-
xs.reduceLeft(max(ord))
27+
def maxElement[A](as: List[A])(implicit ord: Ord[A]): A =
28+
as.reduceLeft(max(_, _)(ord))
3329
```
30+
{% endtab %}
31+
{% tab 'Scala 3' %}
32+
```scala
33+
def maxElement[A](as: List[A])(using ord: Ord[A]): A =
34+
as.reduceLeft(max(_, _)(using ord))
35+
```
36+
{% endtab %}
37+
{% endtabs %}
38+
39+
上面这个 `maxElement` 方法只接受一个类型为 `Ord[A]`_上下文参数_ 并将其作为实参传给 `max` 方法。
3440

35-
在该代码中,参数名称 `ord` 实际上不是必需的;它可以作为推断参数传递给 `max`,因此您只需声明 `maximum` 使用的类型 `Ord[A]` 而不必给它命名:
41+
完整起见,以下是 `max``Ord` 的定义(注意,在实践中我们会使用 `List` 中已有的 `max` 方法 ,
42+
但我们为了说明目的而编造了这个例子):
3643

44+
{% tabs context-bounds-max-ord class=tabs-scala-version %}
45+
{% tab 'Scala 2' %}
3746
```scala
38-
def maximum[A](xs: List[A])(using Ord[A]): A =
39-
xs.reduceLeft(max)
47+
/** Defines how to compare values of type `A` */
48+
trait Ord[A] {
49+
def greaterThan(a1: A, a2: A): Boolean
50+
}
51+
52+
/** Returns the maximum of two values */
53+
def max[A](a1: A, a2: A)(implicit ord: Ord[A]): A =
54+
if (ord.greaterThan(a1, a2)) a1 else a2
4055
```
56+
{% endtab %}
57+
58+
{% tab 'Scala 3' %}
59+
```scala
60+
/** Defines how to compare values of type `A` */
61+
trait Ord[A]:
62+
def greaterThan(a1: A, a2: A): Boolean
63+
64+
/** Returns the maximum of two values */
65+
def max[A](a1: A, a2: A)(using ord: Ord[A]): A =
66+
if ord.greaterThan(a1, a2) then a1 else a2
67+
```
68+
{% endtab %}
69+
{% endtabs %}
70+
71+
`max` 方法用了类型为 `Ord[A]` 的上下文参数, 就像 `maxElement` 方法一样。
72+
73+
## 省略上下文参数
74+
75+
因为 `ord``max` 方法的上下文参数,当我们调用方法 `max` 时, 编译器可以在 `maxElement` 的实现中为我们提供它:
76+
77+
{% tabs context-bounds-context class=tabs-scala-version %}
78+
{% tab 'Scala 2' %}
79+
```scala
80+
def maxElement[A](as: List[A])(implicit ord: Ord[A]): A =
81+
as.reduceLeft(max(_, _))
82+
```
83+
{% endtab %}
84+
85+
{% tab 'Scala 3' %}
86+
```scala
87+
def maxElement[A](as: List[A])(using Ord[A]): A =
88+
as.reduceLeft(max(_, _))
89+
```
90+
91+
注意,因为我们不用显示传递给 `max` 方法,我们可以在 `maxElement` 定义里不命名。
92+
这是 _匿名上下文参数_
93+
{% endtab %}
94+
{% endtabs %}
4195

4296
## 上下文绑定
4397

44-
鉴于此背景,_上下文绑定_是一种简写语法,用于表达“依赖于类型参数的上下文参数”模式。
98+
鉴于此背景,_上下文绑定_ 是一种简写语法,用于表达“依赖于类型参数的上下文参数”模式。
4599

46-
使用上下文绑定,`maximum` 方法可以这样写:
100+
使用上下文绑定,`maxElement` 方法可以这样写:
47101

102+
{% tabs context-bounds-max-rewritten %}
103+
{% tab 'Scala 2 and 3' %}
48104
```scala
49-
def maximum[A: Ord](xs: List[A]): A = xs.reduceLeft(max)
105+
def maxElement[A: Ord](as: List[A]): A =
106+
as.reduceLeft(max(_, _))
50107
```
108+
{% endtab %}
109+
{% endtabs %}
51110

52111
方法或类的类型参数 `A`,有类似 `:Ord` 的绑定,它表示有 `Ord[A]` 的上下文参数。
112+
在后台,编译器将此语法转换为“背景”部分中显示的语法。
53113

54114
有关上下文绑定的更多信息,请参阅 Scala 常见问题解答的 [“什么是上下文绑定?”](https://docs.scala-lang.org/tutorials/FAQ/context-bounds.html) 部分。

0 commit comments

Comments
 (0)