说到函数式编程,函数自然在其中扮演着举足轻重的角色,本讲开始,我们将会去尝试理解在函数式编程中一些重要的函数概念
高阶函数(higher-order function)
在函数是第一类公民的语言中,我们可以做到一件比较有趣的事。即函数可以作为入参或者出参而存在。而高阶函数呢,则是入参或出参是函数或兼而有之的函数,这件事在我们序章的时候其实已经做到过一次了,没错,就是SwapArgs
Func<int, int, bool> SwapArgs(Func<int, int, bool> func)
{
return (a, b) => func(b, a);
}
类似SwapArgs这种类型的函数也可以叫做适配器函数,我们可以按自己喜好去修改函数的入参。不知读者是否之前想过函数的定义是否能够修改的问题,在这里适配器函数告诉我们,函数的入参等并不是一成不变的。
在我们最常见的功能中,Linq就是我们最常见的,基于扩展函数实现的一系列的高阶函数。
扩展函数本身的特性可以更好的适配函数组合这个概念,我们可以使用这个特性让我们获得更好的函数式体验(如果读者有阅读过微软文档,可能会看到在允许的情况下直接将方法放入类中会更好。但这并不总是正确的,函数式编程提倡数据与逻辑的分离,我们更推荐去使用一些静态类,静态方法。关于这一点我们后续会说到)
那么下面让我们来看Linq是怎么使用的
int[] seq = Enumerable.Range(1, 100).ToArray();
var evens = seq.Where(i => i % 2 == 0);
Console.WriteLine(string.Join(",", evens.Take(5)));
我们通过输入了一个lambda表达式(函数),描述了我们应该怎么处理数据,于是我们就获得了0-100之间可以被2整除的数。where函数就像谓语一样,描述了我们应该做什么。这,就有了可读性的提升,不过我觉得还不够,我们还有办法再提升一点可读性吗?
Func<int, bool> IsMod(int n) => x => x % n == 0; // 高阶函数
evens = seq.Where(IsMod(2));
Console.WriteLine(string.Join(",", evens.Take(5)));
我们还可以用函数生成函数(高阶函数)进一步的去简化代码,增强可读性,也兼具一些通用性。
var modby3 = seq.Where(IsMod(3));
Console.WriteLine(string.Join(",", modby3.Take(5)));
Linq的强大性只要使用过或许都会有着深刻的印象,
如果我们想自己实现一些类似Linq的函数,yield(迭代器)关键字也可以轻松的帮我们实现我们的目的
public static class MyLinq
{
public static IEnumerable<TSource> MyWhere<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
foreach (var item in source)
{
if (predicate(item))
yield return item;
}
}
}
是不是比想象中要简单不少呢?</

最低0.47元/天 解锁文章
927

被折叠的 条评论
为什么被折叠?



