关于函数式和抽象的那点事
承接上文回复中的内容,先说明一下:我这将近两年碰到任何问题都会先尝试寻找FP的思路(而不仅仅是形式)解决。无论语言是C++、C#、Python、JS,无论目标的特点是什么样。当然可能有人就会说“你在不适合FP的地方如何如何...”,但是我采取这样的策略,正是为了搞清楚FP在思路和形式两方面上的适用范围。
其中一部分问题的解决特别顺理成章,同时设计和实现确实体现出FP抽象方式的特点;还有一部分情况如果仔细掂量,就会发现和使用命令式下子方法论仅仅在形式上有所区别。这两部分无论哪种,就像脑袋说的使用OO作为工具也同样可行,仅仅是舒适度有差异。
但总有一部分情况,最终感到FP不那么合适而必须退回到一个命令式的设计。这一类情况即便在JS这样还算原生支持FP的语言中,也会感到如果采用FP方式去设计,无论从思路还是在形式上都有太多让人别扭的地方(相对于用OO代替FP仅仅是不那么舒服)。
从熟悉命令式的程序员的角度出发,这个问题我想不在于我作为标本是到底是有一定FP功底了还是略知皮毛。我想大多数命令式起家并且长期使用命令式语言,但是对FP感兴趣的朋友,至少在这小两年内,一般来说也不会比我更有这样的空闲时间和自由度的在实际问题上去尝试了。
另一方面,我也不敢说我对FP的掌握够了,主要是我不是在和比如陈猫老兄一块工作,这使得我碰见一些我认为FP极端不好处理的情形时,不知道其他人是不是也没有这方面的思路。但我的主观感受就是这样:存在一大类问题,如果用纯FP去解决,实在是要绕太多弯子。
我的自我感觉是,这些问题里有一些可能是我的FP功力不够所以没找到正确的方法,但绝对有一些问题是因为FP本身的不适用(关键在于以某一视角看待问题的切入角度)所造成的;而命令式风格下所产生的思路,这种“不适用”的情况较FP要少。
比如LR(k)算法,如果用比较纯的FP思路并采取相应的形式实现,能像命令式那么舒服吗?但是相反的,LL(k)的递归下降实现(即可以是纯FP也可以不是),就很容易被修改为使用命令式下的预测分析法实现;同时即便是以命令式的思路实现的递归下降法也要更容易一些。
另一个例子是正则的自动机使用FP的思路还是比较好处理的,可能的一个重点是围绕五元组中的delta函数(因为它是最难处理的)展开的设计;而两个语言的连接、并、闭包,都可以求一个新的delta函数。如果仅仅实现教科书中的内容,这还是很顺利的。
但是围绕这个方式进行更多的工作的时候,我感觉在很多(进一步的)方面会受到制肘。反过来使用一组对象表示图中的元素虽然也会让一个解决具体问题的自动机产生不少冗余,可总体上还是要比FP方式更加直观、也容易进行各种各样的调整和修改。
更普遍的如我写的一些JS组件,这些组件从命令式的角度来看将会使用大量的中间数据结构和状态。转换到纯FP风格,也许要求有一套monad的框架(为了效率),或者靠不断产生新的计算结果(无论是对象还是函数)。一旦产生高一个层次的组织需要,如果仅仅使用FP范畴内的概念就会麻烦许多。
最终一个项目里还是既有FP又有OO,但是在接口处如何保证风格的过渡,让整个项目显得比较统一,又是需要下一定功夫的。(原来和脑袋也讨论过)
在这些方面,不只是我这样唱衰的人好好使用过没有,认为命令式程序员学习FP利大于弊的同志们,你们的经验又是什么样的?很遗憾社区里也缺乏这样的交流,这使得对比而言FP的学习效率更差一些,也是FP的学习变得*性价比*很低的一个原因(上一篇文章没有提到)。
关于SICP所传授的抽象思维,这个其实在上一篇文章中也不是完全没有涉及。当时我的意思是,同样(或者说在效果上等价的)的抽象思维,通过任何一种命令式下面的子风格方法论,也是可以逐渐掌握的,没有必要说非学习什么思路不可,尤其是考虑到时间上的花销。
尤其是问一下这个问题:某一种抽象就是非掌握不可吗?
“且想象一个多面体是空心的,其表面由薄橡胶制成。我们若切去一面,便可使余下的表面平铺拉伸于一个平面上而不撕破它....”
上面的思想来自于柯西[1813a]对欧拉多面体猜想的证明。
在这里引用它不是为了故弄玄虚,而是为了说明,对人们(即便是那些让人高山仰止的家伙)寻找思路及表述该思路有益的过程,很大程度上是抽离于各种层次的抽象工具的。而SICP等教科书所讲授的方式方法,实则是太具体了,仅仅是若干工具中的一种。
我并不是反对FP或者什么(比如通过SICP学习某些抽象方式),谁用FP舒服谁就用(包括我自己),关键是走一趟我这样的学习与实践的过程值不值。如果一个人比我有更强的能力,或者无论什么原因(内在的外在的)有信心用较小的投入获得足够的收益,当然可以学习FP。
我的结论仅仅像winter-cn替我总结的那样:无论是为了更好的解决问题还是继续提高自身能力,都应避免盲目求助于某一种尚未掌握的、并非不可替代的特定抽象工具的学习。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
2008-07-17 一些待解的疑问