@@ -1274,7 +1274,7 @@ public class Closure9 {
12741274
12751275### 作为闭包的内部类
12761276
1277- 我们可以复制我们的例子使用匿名内部类 :
1277+ 我们可以使用匿名内部类重写之前的例子 :
12781278
12791279``` java
12801280// functional/AnonymousClosure.java
@@ -1300,7 +1300,7 @@ public class AnonymousClosure {
13001300## 函数组合
13011301
13021302
1303- 函数组合(Function Composition)意为“多个函数组合成新函数”。它通常是函数式编程的基本组成部分。在前面的 ` TransformFunction.java ` 类中,有一个使用 ` andThen() ` 的函数组合示例。在 ` java.util.function ` 包里包含支持函数组合的一些接口方法 [ ^ 7 ] 。
1303+ 函数组合(Function Composition)意为“多个函数组合成新函数”。它通常是函数式编程的基本组成部分。在前面的 ` TransformFunction.java ` 类中,有一个使用 ` andThen() ` 的函数组合示例。一些 ` java.util.function ` 接口中包含支持函数组合的方法 [ ^ 7 ] 。
13041304
13051305| 组合方法 | 支持接口 |
13061306| :----- | :----- |
@@ -1343,7 +1343,7 @@ _fter _ll _mbul_nces
13431343
13441344这里我们重点看正在创建的新函数 ` f4 ` 。它调用 ` apply() ` 的方式与常规几乎无异[ ^ 8 ] 。
13451345
1346- 当 ` f1 ` 获得字符串时,它已经被` f2 ` 剥离了前三个字符。这是因为对 ` compose(f2) ` 的调用意味着在 ` f1 ` 之前调用 ` f2 ` 。
1346+ 当 ` f1 ` 获得字符串时,它已经被` f2 ` 剥离了前三个字符。这是因为 ` compose(f2) ` 表示 ` f2 ` 的调用发生在 ` f1 ` 之前 。
13471347
13481348下例是 ` Predicate ` 的逻辑运算演示.代码示例:
13491349
@@ -1376,14 +1376,13 @@ foobaz
13761376
13771377` p4 ` 获取到了所有断言并组合成一个更复杂的断言。解读:如果字符串中不包含 ` bar ` 且长度小于 5,或者它包含 ` foo ` ,则结果为 ` true ` 。
13781378
1379- 正因它产生如此清晰的语法,我在主方法中采用了一些小技巧,并借用了下一章的内容。首先,我创建一个流的字符串对象集合 ,然后将每个对象传递给 ` filter() ` 操作。 ` filter() ` 使用 ` p4 ` 的断言来确定对象的去留。最后我们使用 ` forEach() ` 和 ` println ` 方法打印出留下来的对象 。
1379+ 正因它产生如此清晰的语法,我在主方法中采用了一些小技巧,并借用了下一章的内容。首先,我创建了一个字符串对象的流 ,然后将每个对象传递给 ` filter() ` 操作。 ` filter() ` 使用 ` p4 ` 的断言来确定对象的去留。最后我们使用 ` forEach() ` 将 ` println ` 方法引用应用在每个留存的对象上 。
13801380
13811381从输出结果我们可以看到 ` p4 ` 的工作流程:任何带有 ` foo ` 的东西都会留下,即使它的长度大于 5。 ` fongopuckey ` 因长度超出和不包含 ` bar ` 而被丢弃。
13821382
13831383<!-- Currying and Partial Evaluation -->
13841384## 柯里化和部分求值
13851385
1386-
13871386[ 柯里化] ( https://en.wikipedia.org/wiki/Currying ) (Currying)的名称来自于其发明者之一 * Haskell Curry* 。他可能是计算机领域唯一名字被命名重要概念的人(另外就是 Haskell 编程语言)。 柯里化意为:将一个多参数的函数,转换为一系列单参数函数。
13881387
13891388``` java
@@ -1458,7 +1457,7 @@ public class Curry3Args {
14581457Hi Ho Hup
14591458```
14601459
1461- 对于每个级别的箭头级联(Arrow-cascading),你可以围绕类型声明包装成另一个函数 。
1460+ 对于每个级别的箭头级联(Arrow-cascading),你在类型声明中包裹了另一个 ** Function ** 。
14621461
14631462处理基本类型和装箱时,请使用适当的 ** Function** 接口:
14641463
@@ -1473,7 +1472,7 @@ public class CurriedIntAdd {
14731472 curriedIntAdd = a - > b - > a + b;
14741473 IntUnaryOperator add4 = curriedIntAdd. apply(4 );
14751474 System . out. println(add4. applyAsInt(5 ));
1476- }
1475+ }
14771476}
14781477```
14791478
@@ -1483,13 +1482,13 @@ public class CurriedIntAdd {
148314829
14841483```
14851484
1486- 更多柯里化示例,可搜索互联网。通常这些是 Java 以外的语言,理解它们的基本概念,就应该很容易翻译 。
1485+ 可以在互联网上找到更多的柯里化示例。通常它们是用 Java 之外的语言实现的,但如果理解了柯里化的基本概念,你可以很轻松地用 Java 实现它们 。
14871486
14881487<!-- Pure Functional Programming -->
14891488## 纯函数式编程
14901489
14911490
1492- 即使没有函数式支持,像 C 这样的基础语言,也可以按照一定的原则编写纯函数程序 。Java 8 让函数式编程更简单,不过我们要确保一切是 ` final ` 的,同时你的所有方法和函数没有副作用。因为 Java 在本质上并非是不可变语言,我们无法通过编译器查错。
1491+ 即使没有函数式支持,像 C 这样的基础语言,也可以按照一定的原则编写纯函数式程序 。Java 8 让函数式编程更简单,不过我们要确保一切是 ` final ` 的,同时你的所有方法和函数没有副作用。因为 Java 在本质上并非是不可变语言,我们无法通过编译器查错。
14931492
14941493这种情况下,我们可以借助第三方工具[ ^ 9 ] ,但使用 Scala 或 Clojure 这样的语言可能更简单。因为它们从一开始就是为保持不变性而设计的。你可以采用这些语言来编写你的 Java 项目的一部分。如果必须要用纯函数式编写,则可以用 Scala(需要一些规则) 或 Clojure (需要的规则更少)。虽然 Java 支持[ 并发编程] ( ./24-Concurrent-Programming.md ) ,但如果这是你项目的核心部分,你应该考虑在项目部分功能中使用 ` Scala ` 或 ` Clojure ` 之类的语言。
14951494
@@ -1509,7 +1508,7 @@ Lambda 表达式和方法引用并没有将 Java 转换成函数式语言,而
15091508
15101509[ ^ 1 ] : 功能粘贴在一起的方法的确有点与众不同,但它仍不失为一个库。
15111510[ ^ 2 ] : 例如,这个电子书是利用 [ Pandoc] ( http://pandoc.org/ ) 制作出来的,它是用纯函数式语言 [ Haskell] ( https://www.haskell.org/ ) 编写的一个程序 。
1512- [ ^ 3 ] : 有时函数式语言将其描述为“代码即数据”。“
1511+ [ ^ 3 ] : 有时函数式语言将其描述为“代码即数据”。
15131512[ ^ 4 ] : 这个语法来自 C++。
15141513[ ^ 5 ] : 我还没有验证过这种说法。
15151514[ ^ 6 ] : 当你理解了[ 并发编程] ( ./24-Concurrent-Programming.md ) 章节的内容,你就能明白为什么更改共享变量 “不是线程安全的” 的了。
0 commit comments