
函数式编程
文章平均质量分 87
RuntimeCube
这个作者很懒,什么都没留下…
展开
-
[Unity] Unity 2017 中的 Async - Await代替协程
英文原文:http://www.stevevermeulen.com/index.php/2017/09/using-async-await-in-unity3d-2017/在 Unity 中使用协程通常是解决某些问题的好方法,但它也有一些缺点:协程不能返回值。这鼓励程序员创建庞大的整体协同程序方法,而不是由许多较小的方法组合而成。存在一些变通方法,例如将 Action<> 类型的回调参数传递给协程,或者在协程完成后强制转换从协程产生的最终无类型值,但这些方法使用起来很尴尬并且容易翻译 2022-04-11 22:47:46 · 3190 阅读 · 0 评论 -
#函数式编程 Functional Programming in C# [37]
使用多参数函数有效地进行排序本章包括使用具有提升类型的多参数函数在任何 monadic 类型中使用 LINQ 语法基于属性的测试的基本原理 本章的主要目的是教你在有效类型的世界中使用多参数函数,所以标题中的 "有效 "也是一个双关语。请记住,有效类型是指诸如Option(增加了可选性的效果)、Exceptional(异常处理)、IEnumerable(聚合)和其他类型。 在第三部分,你会看到更多与状态、, laziness 和异步相关的效果。 随着你的代码功能的增加,你将会非常依赖这些效翻译 2021-09-20 22:49:01 · 211 阅读 · 0 评论 -
#函数式编程 Functional Programming in C# [36]
7.6 将列表减少为单个值 将一个值的列表缩减为一个单一的值是一个常见的操作,但我们到目前为止还没有讨论过。在FP术语中,这种操作被称为fold或reduce,这些是你在大多数语言或库以及FP文献中都会遇到的名称。从字面上看,LINQ使用了一个不同的名字:Aggregate。 如果你已经熟悉了Aggregate,你可以跳过下一小节。7.6.1 LINQ 的Aggregate方法 请注意,到目前为止,我们用IEnumerable使用的大多数函数也会返回一个IEnumerable。 例如,Map接收一翻译 2021-09-19 22:54:37 · 179 阅读 · 0 评论 -
#函数式编程 Functional Programming in C# [35]
7.5 模块化和组成一个应用程序 随着应用程序的增长,我们需要将其模块化,并将其分解为各个组成部分。例如,在第6章中,你看到了一个处理转账请求的端到端例子。 我们把所有的代码放在控制器中,最后控制器中的成员列表是这样的。清单 7.9 一个责任太多的控制器?public class BookTransferController: Controller { DateTime now; static readonly Regex regex = new Regex("^[A-Z]{6}翻译 2021-09-19 20:58:16 · 194 阅读 · 0 评论 -
#函数式编程 Functional Programming in C# [34]
7.4 创建对部分应用程序友好的 API 现在您已经了解了部分应用的基本机制,以及如何通过使用 Funcs 而不是方法来解决糟糕的类型推断,我们可以继续进行更复杂的场景,在该场景中我们将使用第三方库和真实的世界要求。 部分应用程序的一个好场景是,当一个函数需要一些在启动时可用且不会改变的配置,以及随着每次调用而变化的更多瞬态参数。在这种情况下,引导组件可以提供配置参数,获得只需要调用特定参数的专用函数。然后可以将其提供给功能的最终消费者,因此无需了解有关配置的任何信息。 在本节中,我们将看这样一翻译 2021-09-19 15:01:36 · 227 阅读 · 0 评论 -
#函数式编程 Functional Programming in C# [33]
7.3 柯里(Curried)函数:针对部分应用进行了优化 以数学家Haskell Curry的名字命名,柯里化是将一个接受参数t1, t2, …, tn的n次方函数f转化为一个接受t1并产生一个接受takest2的新函数,以此类推,最终在参数全部给出后返回与f相同的结果。 换句话说,一个带有签名的 n 元函数(T1, T2, …, Tn) -> RCurried的时候,具有标志性的T1 -> T2 -> … -> Tn -> R 你已经在本章的第一部翻译 2021-09-19 10:26:58 · 228 阅读 · 0 评论 -
#函数式编程 Functional Programming in C# [32]
7.2 克服方法解析的怪癖 到目前为止,我们已经自由地使用方法、lambdas和委托来表示函数。然而,对于编译器来说,这些都是不同的东西,而且方法的类型推理并不像我们希望的那样好。 让我们首先看看当一切顺利时会发生什么,比如当我们使用 Option.Map 时:Some(9.0).Map(Math.Sqrt) // => 3.0 这里,Math.Sqrt这个名字标识了一个方法,而Map期望一个Func<T,R>类型的委托。 更确切地说,Math.Sqrt标识了一个 “方法组翻译 2021-09-19 09:22:14 · 169 阅读 · 0 评论 -
#函数式编程 Functional Programming in C# [31]
用函数构建应用程序本章涵盖部分应用和凝结绕过方法类型推理的限制考虑每个函数级别的依赖关系模块化的编写应用程序将列表减少为单个值 构建一个复杂的、真实的应用程序并非易事。有很多关于这个主题的书,所以本章的目的绝不是提供一个全面的观点。我们将重点介绍可用于模块化和组合完全由函数组成的应用程序的技术,以及结果与 OOP 中通常如何完成的比较。 我们将逐步达到这个目的。 首先,你需要了解一个经典但相当低级的函数技术,即部分应用。 这允许你编写高度通用的函数,其行为是参数化的,然后提供这些翻译 2021-09-17 22:28:45 · 130 阅读 · 0 评论 -
#函数式编程 Functional Programming in C# [30]
6.5 Either主题的变化 Either使我们在函数式错误处理方面有了长足的进步。 异常会导致程序 "跳出 "正常的执行流程,进入堆栈中某个任意函数的异常处理块,与此相反,Either保持了正常的程序执行流程,而是返回一个结果的表示。 因此,Either 有很多值得喜欢的地方。还有一些可能的反对意见:Left 的类型总是保持不变,那么你如何组成函数,以不同的 Left 类型返回一个Either?总是要指定两个通用参数使得代码过于冗长。“Either”、“Left”和“Right”这些名字翻译 2021-09-17 20:22:14 · 273 阅读 · 0 评论 -
#函数式编程 Functional Programming in C# [29]
6.4 向客户端应用程序表示结果 现在你已经看到了很多使用Option和Either的用例。这两种类型都可以被看作是代表结果:在Option的情况下,None可以表示失败;在Either的情况下,它是Left。我们已经将Option和Either定义为C#类型,但在本节中你将看到如何将它们转化到外部世界。 尽管我们已经为这两种类型定义了 Match,但我们很少使用它,而是依靠 Map, Bind, 和 Where 来定义工作流。 请记住,这里的关键区别在于后者是在抽象的范围内工作(比如说你从 Opt翻译 2021-09-16 20:26:12 · 166 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [28]
6.3 验证:Either 的完美用例 让我们重新审视请求转账的场景,但在这种情况下,我们将处理更简单的场景,在该场景中,客户明确请求在未来某个日期进行转账。 应用程序应执行以下操作:验证请求。存储转账详细信息以备将来执行。返回带有成功指示或任何失败详细信息的响应。 我们可以用Either来模拟该操作可能失败的事实。如果传输请求被成功存储,就没有任何有意义的数据可以返回给客户端,所以Right类型参数将是Unit。Left 的类型应该是什么?6.3.1 为错误选择一个合适的表述翻译 2021-09-15 22:10:18 · 180 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [27]
6.2 可能失败的链式操作翻译 2021-09-15 19:53:31 · 204 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [26]
成为函数式 在这一部分中,我们将建立在迄今所奠定的基础上,你将看到在第一部分中为有限的场景所介绍的一些技术是如何被推广的,使你能够以函数式风格来编写整个应用程序。 第6章讨论了对验证和错误处理的功能取舍。 第7章展示了你如何使用部分应用和强大的聚合函数(fold)等技术,将应用程序模块化并只用函数组成。 第8章讨论了另一个核心函数Apply,它还教你如何实现LINQ查询模式,并比较了一些函数式样,如applicatives和monads。 第8章还介绍了一种叫做基于属性的测试的技术,它通过向翻译 2021-09-14 22:32:12 · 398 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [25]
5.5 端到端的服务器端工作流 现在,我们已经有了主要的工作流程骨架和简单的领域模型,我们准备完成端到端的工作流程。我们仍然需要实现Book函数,它应该做以下事情:加载帐户。如果账户有足够的资金,从账户中扣款。保留对帐户的更改。通过 SWIFT 网络电汇资金。 让我们定义两个服务,捕获DB访问和SWIFT访问。public interface IRepository<T>{ Option<T> Get(Guid id); void Save(Guid id,翻译 2021-09-14 20:25:07 · 284 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [24]
5.4 函数域建模的介绍 领域建模意味着为有关业务领域的实体和行为创建一个表示。在这个案例中,我们需要一个银行账户的表示,转移的资金将从这个账户中扣除。我们将在第9章中更详细地研究领域建模,但在当前的情况下看到基本原理是很好的。 让我们从一个简单得可笑的银行账户的表示开始,它只记录了账户的余额。这足以说明OO和函数式方法之间的根本区别。一个OO的实现可能看起来像这样。清单5.6 在OOP中,对象同时捕获数据和行为public class Account{ public decimal Ba翻译 2021-09-14 16:47:57 · 141 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [23]
5.3 编程工作流程 工作流是理解和表达应用需求的一种强有力的方式。一个工作流程是一个有意义的操作序列,导致一个期望的结果。例如,一个烹饪食谱描述了准备一道菜的工作流程。翻译 2021-09-14 16:04:33 · 221 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [22]
5.2 从数据流的角度思考 您可以使用函数组合编写整个程序。每个函数都以某种方式处理它的输入,而输出成为下一个函数的输入。当你这样做时,你开始从数据流的角度看你的程序:程序只是一组函数,数据流过程序,通过一个功能进入下一个功能。图 5.1 说明了一个线性流程——最简单和最有用的一种。5.2.1 使用 LINQ 的可组合 API 在前面的例子中,我们通过使AbbreviateName和AppendDomain方法成为扩展方法而使其成为可链。这也是LINQ设计中采取的方法,如果你看一下System.翻译 2021-09-13 14:41:47 · 297 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [21]
用函数组合设计程序本章包括用函数组合和方法链来定义工作流编写组合良好的函数使用工作流处理服务器请求的端到端示例 函数组合不仅功能强大,表现力强,而且工作起来也很愉快。它在某种程度上被用于任何编程风格,但在FP中,它被广泛地使用。例如,你是否注意到,当你使用LINQ来处理列表时,只需几行代码就能完成很多工作?这是因为LINQ是一个功能性的API,在设计时考虑到了组合。 在这一章中,我们将介绍函数编译的基本概念和技术,并说明它在LINQ中的应用。 我们还将实现一个端到端的服务器端工作流,翻译 2021-09-13 14:16:54 · 355 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [20]
4.6 不同抽象层次的编码 抽象(在英语中,而不是在OOP中)意味着不同具体事物的具体特征被去除,以便出现一个一般的、共同的特征:一个概念。例如,当你说 "你会看到一排房子 "或 "把你的鸭子排成一排 "时,"排 "的概念去掉了任何使鸭子与房子不同的东西,而只是捕捉它们的空间布局。 IEnumerable和Option的核心就是这种概念上的抽象:它们内部值的所有具体特征都被抽象掉了;这些类型只包含了枚举值的能力,或者说可能不存在一个值的能力,分别如此。对于大多数通用类型也是如此。 让我们试着归纳翻译 2021-09-13 12:39:45 · 302 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [19]
4.5 结合 Option 和 IEnumerable 与 Bind 我已经提到,看待 Option 的一种方式是将其作为一个列表的特例,它既可以是空的(None),也可以正好包含一个值(Some)。你甚至可以在代码中表达这一点,把一个Option转换为一个IEnumerable,如下所示:public struct Option<T>{ public IEnumerable<T> AsEnumerable() { if (IsSome) yield retur翻译 2021-09-12 19:08:41 · 208 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [18]
4.4 使用 Where 过滤值 在第1章中,你看到了Where在过滤IEnumerable值方面的几种用法。事实证明,Where也可以被定义为Option。清单 4.5 过滤Option的内部值public static Option < T > Where < T > (this Option < T > optT, Func < T, bool > pred) => optT.Match( () => None,翻译 2021-09-12 17:35:53 · 235 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [17]
4.3 使用 Bind 串联函数 绑定是另一个非常重要的函数,与Map类似,但稍微复杂一些。我将用一个简单的例子来介绍对Bind的需求。假设你想要一个简单的程序,从控制台中读取用户的年龄,并打印出一些相关的信息,你还想要错误处理:年龄应该是有效的!这就是Bind。 记得在上一章中,我们定义了Int.Parse来解析一个字符串为一个int.我们还定义了Age.Of,一个智能构造函数,从给定的int创建一个Age实例。这两个函数都返回一个Option:Int.Parse : string ->翻译 2021-09-12 17:16:59 · 327 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [16]
4.2 使用 ForEach 执行副作用 在第三章中,我们讨论了Func和Action之间的二分法。 我们在Map中又遇到了这个问题。Map需要一个Func,那么如果我们想对给定结构中的每个值执行一个Action,我们该怎么做? 您可能知道 List 有一个 ForEach 方法,它接受一个 Action,它为列表中的每个项目调用:using static System.Console;new List<int> { 1, 2, 3 }.ForEach(Write);// pri翻译 2021-09-12 15:17:39 · 203 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [15]
函数式编程中的模式在本章中核心函数 Map、Bind、Where 和 ForEach介绍 functors 和 monads在不同的抽象层次上工作 模式是一种可以应用于解决各种问题的解决方案。我们将在本章中讨论的patterns是简单的函数;这些函数在进行功能编码时无处不在,可以被看作是FP的核心功能。 你可能已经熟悉了其中的一些函数,比如Where和Select,在IEnumerable中使用过它们。但你会发现,同样的操作可以应用于其他结构,从而建立起一种模式。 在本章中,我将用Opt翻译 2021-09-10 22:19:12 · 540 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [14]
3.4 使用 Option 对可能缺少数据的情况进行建模 Option类型被用来表示没有数据的可能性,在C#和其他许多编程语言(以及数据库)中,通常用null来表示。 我希望向你展示Option对可能不存在的数据给出了一个更稳健和富有表现力的表示。3.4.1 你每天使用的糟糕 API 在框架库中,表示可能没有数据的问题并没有得到很好的处理。想象一下,你去参加一个工作面试,得到了以下的测验:问题:这个程序打印什么?using System;using System.Collections.Ge翻译 2021-09-10 13:33:31 · 620 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [13]
3.3 使用 Unit 对数据缺失进行建模 我们已经讨论了如何表示数据;当没有数据可表示时怎么办?许多函数被调用时,其副作用是返回无效。但这与许多函数式技术并不兼容,所以在这一节中,我将介绍Unit:一个可以用来表示没有数据的类型,而没有void的问题。3.3.1 为什么 void 不理想 让我首先说明为什么 void 不太理想。在第 1 章中,我们介绍了通用的 Func 和 Action 委托系列。但是,如果它们如此通用,为什么我们需要其中的两个?为什么我们不能只用 Func 来表示一个不返回任翻译 2021-09-07 13:49:11 · 245 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [12]
3.2 用数据对象捕获数据 本章的大部分内容将侧重于表示数据缺失或可能缺失的方法。这些看起来有些抽象的概念,所以让我们从当我们确实有一些数据要表示时会发生什么开始。 为了表示数据,我们使用数据对象:包含数据但没有逻辑的对象。这些也称为“贫血”对象,但名称中没有负面含义。 在FP(与 OOP 不同)中很自然地将逻辑和数据分开:逻辑被编码在函数中。使用数据对象捕获数据,这些数据对象用作这些功能的输入和输出。 想象一下,在人寿保险或健康保险的应用中,你需要写一个函数,根据客户的年龄来计算客户的翻译 2021-09-07 13:19:32 · 265 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [11]
设计函数签名和类型本章涵盖精心设计的函数签名对函数输入的细粒度控制使用 Option 表示可能缺少数据 到目前为止,我们介绍的原则定义了一般的函数式编程,无论您是使用静态类型语言(如 C#)还是动态类型语言(如 JavaScript)进行编程。在本章中,您将学习一些特定于静态类型语言的函数式技术:因为函数和它们的参数都是类型化的,这就打开了一整套有趣的考虑。 函数是函数式程序的构件,因此,正确掌握函数的签名是最重要的。因为函数签名是根据其输入和输出的类型来定义的,所以正确地掌握这些类翻译 2021-09-06 16:46:18 · 495 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [10]
2.4 计算的纯度和进化 我希望本章使函数纯度的概念不再那么神秘,并说明了为什么扩展纯代码的足迹是一个有价值的目标,提高代码的可维护性和可测试性。 软件和硬件的进化也对我们如何看待纯度产生重要影响。我们的系统越来越分散,因此我们程序的 I/O 部分越来越重要。随着微服务架构成为主流,我们的程序不再进行计算,而更多地将计算委托给其他服务,它们通过 I/O 与之通信。 I/O 要求的增加意味着纯度更难实现。但这也意味着对异步 I/O 的需求增加,正如您所见,纯度可以帮助您处理并发场景,其中包括处理异翻译 2021-09-06 14:39:10 · 238 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [9]
2.3 纯度和可测试性 在上一节中,你看到了纯函数在并发情况下的特性。 因为副作用与状态突变有关,你可以去掉突变,得到的纯函数可以顺利地并行运行。 现在我们来看看纯函数在单元测试方面的属性,以及在副作用与I/O有关的情况下。与突变不同,你不能避免与I/O有关的影响;突变是一个实现细节,而I/O通常是一个需求。 您可能已经对单元测试有所了解,可以帮助您理解纯度,因为两者是紧密联系在一起的。与上一节一样,本节也应该有助于消除纯度仅具有理论意义的观念——您的经理可能不在乎您是否编写纯函数,但他可能热衷翻译 2021-09-06 14:24:24 · 341 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [8]
2.2 纯度和并发性 现在的理论已经够多了;让我们看看一些演示纯函数和非纯函数作用的代码。想象一下,你想把一个字符串的列表格式化为一个有数字编号的列表;大小写应该是标准化的,而且每个项目应该在前面加上一个计数器。要做到这一点,你将创建一个ListFormatter类,它可以如下使用:var shoppingList = new List<string> { "coffee beans", "BANANAS", "Dates" };new ListFormatter() .Format(翻译 2021-09-06 12:33:57 · 260 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [7]
为什么函数纯度很重要本章涵盖什么使一个函数变得纯粹或不纯粹为什么纯度在并发场景中很重要纯度与可测试性的关系减少代码的不纯足迹 这一章最初的名字是 “纯洁性不可抗拒的吸引力”。但是,如果它是如此不可抗拒,我们就会有更多的函数式程序员,对吗? 正如你在本章中所看到的,纯函数具有一些非常理想的特性,你可以看到,函数式职业程序员对纯函数情有独钟–没有副作用的函数。 不幸的是,对纯函数和你能用它们做什么的迷恋是FP作为一门学科与业界脱节的部分原因。你很快就会意识到,在大多数现实世界的应用中,翻译 2021-09-06 11:06:04 · 374 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [6]
1.6 函数式编程的好处 上一节展示了如何使用HOFs来避免重复,并实现更好的关注点分离。事实上,FP的优势之一就是它的简洁性:你可以用更少的代码行实现同样的结果。将其乘以一个典型应用中的数万行代码,简洁性对应用的可维护性也有积极的影响。 通过应用你在本书中学到的功能技术,还有很多好处,它们大致可分为三类:更干净的代码 —— 除了前面提到的简洁性之外,FP还能使代码更有表现力,更易读,更易测试。 整洁的代码不仅是开发人员的智力享受,而且还能通过减少维护成本为企业带来巨大的经济效益。更好地支持并翻译 2021-09-06 09:49:10 · 406 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [5]
1.5 使用 HOF 避免重复 例如,与数据库的交互需要一些设置来获取和打开一个连接,并在交互之后进行一些清理以关闭连接并将其返回到底层连接池。在代码中,它看起来像下面这样。清单1.12 连接到一个数据库需要进行一些设置和拆解string connString = "myDatabase";//设置:获取并打开连接var conn = new SqlConnection(connString));conn.Open(); // interact with the database.../翻译 2021-09-06 09:40:14 · 447 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [4]
1.4 高阶函数 现在你已经了解了什么是FP,我们也回顾了语言的功能特性,现在是时候开始探索一些具体的功能技术了。我们将从函数作为第一公民的最重要的好处开始:它使你有能力定义高阶函数(HOFs)。 HOFs是将其他函数作为输入或将一个函数作为输出返回的函数,或者两者都是。我假定你已经在某种程度上使用过HOFs,比如用LINQ。在本书中,我们会经常使用HOFs,所以本节应作为复习,并可能介绍一些你可能不太熟悉的HOFs用例。HOFs很有趣,本节中的大多数例子都可以在REPL中运行。请确保你在这一过程中翻译 2021-09-03 14:56:00 · 334 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [3]
1.3 用函数式思考 在本节中,我将澄清我对函数的理解。我将从这个词的数学用法开始,然后转向C#提供的代表函数的各种语言结构。1.3.1 作为映射的函数 在数学中,一个函数是两个集合之间的映射,分别称为域和子域。也就是说,给定其域中的一个元素,函数会产生其子域中的一个元素。这就是全部–不管这个映射是基于某个公式还是完全任意的,都不重要。 在这个意义上,函数是一个完全抽象的数学对象,函数产生的值完全由其输入决定。 你会发现,编程中的函数并不总是这样的。 例如,设想一个将小写字母映射到大写字母翻译 2021-09-03 14:14:38 · 676 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [2]
1.2 C#是一种怎样的功能性语言? 事实上,C#通过Delegate类型从最早的语言版本中就支持函数作为第一公民,随后引入的lambda表达式使语法支持更加完善–我们将在下一节中回顾这些语言特性。 有一些怪癖和限制,比如当涉及到类型推理时;我们将在第8章讨论这些。但总的来说,对函数作为第一公民的支持是相当好的。 至于支持避免原地更新的编程模型,这方面的基本要求是语言要有垃圾收集。因为你创建了修改过的版本,而不是在原地更新现有的值,所以你希望旧版本能在需要时被垃圾回收。同样,C#也满足了这个要求翻译 2021-09-03 12:35:10 · 648 阅读 · 0 评论 -
c#函数式编程 Functional Programming in C# [1]
第1部分核心概念 在这一部分,我们将介绍函数式编程的基本技术和原理。 第 1 章首先介绍什么是函数式编程,以及 C# 如何支持函数式编程。然后深入研究高阶函数,这是 FP 的基本技术。 第 2 章解释了什么是纯函数,为什么纯度对函数的可测试性有重要影响,以及为什么纯函数很适合并行化和其他优化。 第 3 章介绍了设计类型和函数签名的原则——你以为自己知道但从函数的角度来看时会感到耳目一新的事情。 第 4 章介绍了 FP 的一些核心功能:Map、Bind、ForEach 和 Where(过翻译 2021-09-03 10:33:59 · 2207 阅读 · 1 评论