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,
(t) => pred(t) ? optT : None);
给定一个 Option 和一个谓词,如果给定的 Option 是 Some,并且它的内部值满足这个谓词,你就会得到 Some;否则,你会得到 None。同样,如果你把 Option 看作是一个最多只有一个项目的列表,这就说得通了。
下面是一个简单的用法:
bool IsNatural(int i) => i >= 0;
Option<int> ToNatural(string s) => Int.Parse(s).Where(IsNatural);
ToNatural("2") // => Some(2)
ToNatural("-2") // => None
ToNatural("hello") // => None
这里我们以Int.Parse为基础,它已经返回了一个Option,表示字符串是否被正确地解析为一个int,然后我们使用Where来额外地强化这个值是正的。
我们对核心函数的初步探索到此结束。 随着你在本书中的进展,你会看到更多的功能,但到此为止描述的四个功能可以让你走得更远–你将在下一章看到。
核心功能的众多名称
学习FP的障碍之一是,同样的结构在不同的语言或库中被赋予不同的名称。核心函数也是如此,所以我在下面的表格中,当你在其他地方遇到这些同义词时,可以帮助你理解它们。
在编写这本书和LaYumba.Functional库时,我必须决定为这些函数选择什么样的名字,而这些选择必然是有些随意的。ForEach和Where是好名字,也是.NET的标准名称,但Select和SelectMany如果用于IEnumerable以外的functors/monads,则是不好的名字,所以我选择使用Map和Bind,它们更通用、更简短,而且在FP文献中非常标准。