程序的本质是什么?数据结构+算法!!!我想这也是不少程序员给出的答案,我本身也承认这一观点,当咱们了解了某一门编程语以后,接下来咱们面对的每每是数据结构和算法的学习。而如今,我对于程序的本质有了不同的答案:分化和组合。个人老师曾经告诉我,工程师或者程序员有一个很重要的能力(我猜这也是最重要的能力),那就是发现和解决问题。<!-- More -->而我目前只能接触到解决问题的层次,这也是我也一直在探寻的目标 —— 分化和组合。程序员
在现实的程序开发中,咱们碰到的问题通常是一个很大的命题,难以抽象,这时候每每经过分化子问题的方式对程序进行分而治之。在算法里,这种方式叫作分治。算法
将程序分化成能够抽象的子程序以后,再将他们组合成一个具备完备功能的程序。组合是程序或代码可复用的前提,函数式编程中组合的使用也会给咱们带来意向不到的惊喜编程
Haskell是纯函数式编程语言,他的强大不用我多说,这里展现一下他的组合能力。数组
compose :: (b -> c) -> (a -> b) -> a -> c compose f g = f . g
在函数式编程的组合中,咱们是从右到左执行的,上述的例子中咱们借助 (.) 函数实现组合,固然,咱们也能够用本身的方式实现。数据结构
compose :: (b -> c) -> (a -> b) -> a -> c compose f g x = f (g x)
经过 Haskell 强大的类型签名中,大体能够推出compose函数的做用。b -> c
表明了一个从b
类到c
类的映射函数,a -> b
也是同样,compose
函数接受两个函数f
和g
,返回一个新的函数h
,h
函数表达了从a
类到b
类再到c
类的映射。数据结构和算法
举个例子,咱们有sum
函数 —— 给列表求和,odd
函数 —— 判断数字是不是奇数。(简单起见,给他们的类型签名并不许确,但足够简单)编程语言
odd :: Int -> Bool sum :: [Int] -> Int sumIsOdd :: [Int] -> Bool sumIsOdd = compose odd sum sumIsOdd [1,2,34,5]
sumIsOdd
函数组合了求和与判断奇数两个函数,他并没实现具体的功能,而是经过一种通俗的组合实现了将单一的函数转化成稍微复杂的函数,从而达到功能上的扩充,我想这就是组合的魅力,也是函数式的魅力之一吧。函数式编程
JavaScript是一门表现力极强的语言,除了本质上对面向对象的支持,对函数式编程的支持也丝绝不弱,组合函数实现起来虽然复杂,可是也未必不可行,并且相对于Haskell的晦涩,JavaScript更加简单一点函数
const odd = x => x % 2 !== 0; const sum = args => args.reduce((a, b) => a + b); const compose = (...fs) => arg => fs.reduceRight((f, g) => g.call(null, f), arg);
借助ES6的箭头函数实现起来驾轻就熟,可见即使是JavaScript这种以面向对象思想设计的语言也但愿在函数式编程上面能有所建树。学习
顺带一提,对数组扩充的map
、filter
、reduce
等函数,也是JavaScript对函数式编程的支持,虽然只是利用while循环作的语法糖,效率也不如while循环,可是在JavaScript的语境中,不多对效率有极高的要求,因此从语义上来说,我更倾向用函数式的方式解决纯数据的问题。
函数式编程随着多核CPU的发展,开始再次出如今咱们的视野中,有时候也会担忧过于吹捧函数式,反而落入俗套。仔细想一想,编程范式并非一枝独秀的世界,而是百家争鸣的,各有擅长的领域。固然在一些环境下二者也是可以共存的,甚至二者同时带来的收益可能更加可观呢。
说回组合,其实我本身也只是一个半吊子,也须要不断的学习才能对组合有一个更加清晰的认识,而不是拘泥于语言,在实际生产中分化和组合也实在过重要了,并非一两个函数可以归纳的,如今的也我只能以这种简单的方式做了解了。