不仅仅是装逼——函数式的意义
Posted 写程序的康德
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不仅仅是装逼——函数式的意义相关的知识,希望对你有一定的参考价值。
耗子发表了一篇文章,文章写的很棒把一段如天书一般的函数式代码拆解的很清晰,但是他只解释了代码而没有解释这样做的原因,很容易让人产生错觉——函数式生来装逼。如果你读过我之前的《一次函数式编程实践》应该还记得这段话
函数式编程语言不是一些奇技淫巧的语法糖,它是一种不同的编程方式,所以思考问题的方式也不再是思考业务逻辑,寻找对象;而是先思考数据再思考业务逻辑。(关注结果而不是过程)
函数它代表的是一种不同的思考问题方式而不是让人看不懂的装逼代码。我们来看例子中的这段代码
function find (list, y) {
for ( let i = 0; i < list.length; i++ ) {
if ( list[i] == y ) return i;
}
return null;
}
let arr = [0,1,2,3,4,5]
console.log(find(arr, 2))
console.log(find(arr, 8))
逻辑很简单就是从数组list中寻找数字y。当然后面有人写了一段“函数式”的写法,其实这种写法只有浓郁的装逼之风而不是真正的函数式。函数式仅仅是强调不用循环、判断语句而从来没有否定循环和判断结构。截止到目前为止程序设计依然是顺序、循环、分支还没有出现过别的程序设计结构,这个世界依然是结构化程序设计在主导。用函数式编程的本质是不要实现一个复杂的函数来实现结果而是通过一些简单函数层层定义(其实对于问题本身来说完全可以用for语句搞定,它本身就非常简单)。例子中我们是在x中寻找y,如果用一个for循环实现就等于是在思考过程,我们可以尝试变换思路,考虑怎么样利用一个简单的函数组合实现。我们定义一个函数,index_of_element_0
,它判断数组第一个元素是否和y相等,如果相等返回index否则取出第一个元素继续递归。通过这个函数的组合我们可以实现index_of_element(就是我们想要的结果)代码如下:
function index_of_element_0(list, x, y, index){
if(x==y) return index;
let first = list.shift();
return index_of_element_0(list, first, y, index+1);
}
function index_of_element(list, y){
let first = list.shift();
return index_of_element_0(list, first, y, 0);
}
我已经尽可能的用函数式的风格写这段代码了,但是javascript真的不是函数式语言,所以无论如何努力也写不出真正的函数式风格。这段代码看起来依然不够简单明了。所以我写了一段Erlang的代码
比起JavaScript它不但考虑了多种终止条件,而且真的不会修改变量的值。(JavaScript的版本其实会把参数值修改掉,参看shift
方法)
函数式结构的复用
一般的函数式思考问题方法我们会先考虑能否用现有的函数结构解决(比如map、reduce、filter就是一些已经有的函数式结构)如果没有就意味着我们必须自己设计一个函数结构。比如例子中我们就设计了一个index_of_elelment的函数结构,它接收:一个list(就是数组)、一个数据y,输出x在list中的index。这个结构是可以复用的,y可以是数字,字符串,甚至是其他复杂数据类型(你可能需要传递一个cmp函数)
学习函数式的建议
我个人并不认为函数式是非常好的编程实践,它非常晦涩、难懂;所以如果有可能请尽量不要在代码中使用函数式风格。JavaScript肯定不是一个合格的函数式编程语言,它融入了一些语法特性支持函数式的写法但是并没有完全适应函数的思考问题方式,它只是一种函数式语法糖(Java、Python也是如此)。所以把它们当做语法糖用就可以了,否则容易扯着蛋。Haskell、Lisp之类的也是非常鬼扯的东西,它们自称真的函数式但是仅仅就是真正的函数式而已。学术气息大于工程实践意义,为了追求纯粹丝毫不妥协。如果你用它们可能这辈子都没有办法写完代码(某个问题可能涉及到很复杂的学术问题,囧)恩,我要推荐的是Erlang。融合了工程气息和函数式编程的编程语言,它是为了解决并行计算而实现函数式而不是因为函数式而函数式。
欢迎关注公众账号了解更多信息“写程序的康德——思考、批判、理性”
祝大家“自己的节日快乐”
以上是关于不仅仅是装逼——函数式的意义的主要内容,如果未能解决你的问题,请参考以下文章