为什么要学习函数式编程

本文探讨了在学习函数式编程中遇到的问题,通过Unity实现的九宫格案例,展示了Immutable原则如何避免数据操作中的意外。作者解释了错误原因,并对比了命令式和函数式编程思路,提倡理解理论背景以有效应用工具。

引言

我最近正在学习面向数据编程,在此过程中逐渐接触到了函数式编程,并被其理论思想所折服,希望能够和大家分享下我的学习心得。 下面将结合一个实际工程问题,来讨论下函数式编程其中之一的特性:Immutable,以及这种原则是如何来指导我们的实际工作。

实际工程介绍

如图所示,为一个3*3的九宫格,蓝色格子代表其中存放有数据,白色格子代表是个空格子。我的目标是:找到格子(x,y)上下左右四方向中所有的空格子,并将空格坐标以List<VectorInt2>的形式输出。 我的开发环境是Unity2020.1.14。
#错误示范 我觉得代码非常简单,只要 遍历 四个方向的格子就好了,如果格子中有数据就remove掉就好了。据此,很快就写出了代码:
    
//将四方邻近的格子坐标装入List var adjacentGrids = new List < Vector2Int > ( ) ; adjacentGrids . Add ( gridPos + Vector2Int . left ) ; adjacentGrids . Add ( gridPos + Vector2Int . right ) ; adjacentGrids . Add ( gridPos + Vector2Int . up ) ; adjacentGrids . Add ( gridPos + Vector2Int . down ) ; //遍历List foreach ( var item in adjacentGrids ) { if ( HasData ( item ) ) //如果格子中有数据,就从adjacentGrids中remove { adjacentGrids . Remove ( item ) ; } } return adjacentGrids ;
但是测试结果出人意料:adjacentGrids.Count期望值为1,实际运行结果为2或者3。 为什么会这样呢?很奇怪啊!逻辑看上去没有问题,编辑器也没有报错,还出现了两个结果。
#为什么错了 让我们来一步步检查下迭代过程。 第一步,检查左侧格子,没有数据,下一步。 第二步,检查右侧格子,有数据,移除,下一步。 第三步就会出现非常奇怪的事情:第二步中对 adjacentGrids做出了修改,这时编辑器可能会直接终止迭代,可能继续迭代,但会抛出异常。 这就导致了运行结果很奇怪!
#函数式编程是怎样避免这种错误的 函数式编程告诉我们不要直接去操作adjacentGrids,而是要去拷贝adjacentGrids。以下是修改代码:
    
List < Vector2Int > temp = new List < Vector2Int > ( ) ; //temp作为adjacentGrids for ( int i = 0 ; i < 4 ; i ++ ) { if ( ! HasData ( adjacentGrids [ i ] ) ) //如果格子中无数据,将格子坐标压入temp { temp . Add ( adjacentGrids [ i ] ) ; } } return temp ;
但是函数式编程在哪里呢?这些不都是命令式的吗?
对于这些问题,我觉得都无关紧要。我认为明白什么时候会出问题?为什么会出问题?从这个问题中我们能够得到什么?这些理论知识才是重要的。我认为所谓理论是前人经验教训的总结,这些总结比我们的个人教训要更加宝贵。对于函数式编程,我们不要局限于用工具的层面上。要明白什么时候用什么工具才行。
在这个例子中,函数式编程这样解决:
    
return adjacentGrids . Where ( x => ! HasData ( x ) ) . ToList ( ) ;
我用的插件是UniRx,当然使用Rx.Net也可以达到相同的效果。对于具体的语法特性如Where代表什么,可能有读者会感到疑惑。操作符Where的具体工作情况见: http://reactivex.io/
但是无论使用哪种工具都是基于同一种理论,采用同样的操作符名称。很多人抱怨函数式编程很难理解,主要原因在于缺乏一些基础理论的支持。
比如代码中的Where其实就是LinQ中的Where操作符,至于为什么,为此我强烈推荐大家看下这本书《Rx.Net in Action》[1]。这本书很详细的介绍了面向数据、函数式的理论,对于大家的工作会有极大助力。
在之后的文章中,我会结合各种问题对知识点做出介绍。
#参考书目 [1] Tamir Dresher. Rx.Net in Action. https://www.manning.com/books/rx-dot-net-in-action
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值