【C#/F#】「函数式编程」第一讲:高阶函数、纯函数

说到函数式编程,函数自然在其中扮演着举足轻重的角色,本讲开始,我们将会去尝试理解在函数式编程中一些重要的函数概念

高阶函数(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;
        }
    }
}

是不是比想象中要简单不少呢?</

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值