资讯专栏INFORMATION COLUMN

函数式编程之组合

Jinkey / 3288人阅读

摘要:在函数式编程的组合中,我们是从右到左执行的,上述的例子中我们借助函数实现组合,当然,我们也可以用自己的方式实现。小结函数式编程随着多核的发展,开始再次出现在我们的视野中,有时候也会担心过于吹捧函数式,反而落入俗套。

程序的本质是什么?数据结构+算法!!!我想这也是很多程序员给出的答案,我自己也认可这一观点,当我们了解了某一门编程语之后,接下来我们面对的往往是数据结构和算法的学习。而现在,我对于程序的本质有了不一样的答案:分化和组合。我的老师曾经告诉我,工程师或者程序员有一个很重要的能力(我猜这也是最重要的能力),那就是发现和解决问题。而我目前只能接触到解决问题的层次,这也是我也一直在探寻的目标 —— 分化和组合。

分化与组合

在现实的程序开发中,我们碰到的问题一般是一个很大的命题,难以抽象,这时候往往通过分化子问题的方式对程序进行分而治之。在算法里,这种方式叫做分治。

将程序分化成可以抽象的子程序之后,再将他们组合成一个具有完备功能的程序。组合是程序或代码可复用的前提,函数式编程中组合的使用也会给我们带来意向不到的惊喜

Haskell 的组合

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函数接受两个函数fg,返回一个新的函数hh函数表达了从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 的组合

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这种以面向对象思想设计的语言也希望在函数式编程上面能有所建树。

顺带一提,对数组扩充的mapfilterreduce等函数,也是JavaScript对函数式编程的支持,虽然只是利用while循环做的语法糖,效率也不如while循环,但是在JavaScript的语境中,很少对效率有极高的要求,所以从语义上来讲,我更倾向用函数式的方式解决纯数据的问题。

小结

函数式编程随着多核CPU的发展,开始再次出现在我们的视野中,有时候也会担心过于吹捧函数式,反而落入俗套。仔细想想,编程范式并不是一枝独秀的世界,而是百家争鸣的,各有擅长的领域。当然在一些环境下两者也是能够共存的,甚至两者同时带来的收益可能更加可观呢。

说回组合,其实我自己也只是一个半吊子,也需要不断的学习才能对组合有一个更加清晰的认识,而不是拘泥于语言,在实际生产中分化和组合也实在太重要了,并不是一两个函数能够概括的,现在的也我只能以这种简单的方式作了解了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97274.html

相关文章

  • 函数编程的兴衰与当前崛起

    摘要:函数式编程逐渐被边缘化,被抛弃到学术界和非主流的场外。组合式编程的重新崛起年左右,有个巨大的变化爆发了。人们开始逐渐在私下里谈论函数式编程。箭头函数对于函数式编程的爆发起到了推动剂的作用。现在很少看到那种不用函数式编程的大型应用了。 showImg(https://segmentfault.com/img/remote/1460000009036867?w=800&h=364); 本...

    binaryTree 评论0 收藏0
  • JavaScript函数编程,真香组合(一)

    摘要:组合的概念是非常直观的,并不是函数式编程独有的,在我们生活中或者前端开发中处处可见。其实我们函数式编程里面的组合也是类似,函数组合就是一种将已被分解的简单任务组织成复杂的整体过程。在函数式编程的世界中,有这样一种很流行的编程风格。 JavaScript函数式编程,真香之认识函数式编程(一) 该系列文章不是针对前端新手,需要有一定的编程经验,而且了解 JavaScript 里面作用域,闭...

    mengbo 评论0 收藏0
  • JavaScript函数编程函数组合函数compose和pipe的实现

    摘要:函数组合是函数式编程中非常重要的思想,它的实现的思路也没有特别复杂。前者从左向右组合函数,后者方向相反。下面就是一个最简单的可以组合两个函数的在实际应用中,只能组合两个函数的组合函数显然不能满足要求,我们需要可以组合任意个函数的组合函数。 函数组合是函数式编程中非常重要的思想,它的实现的思路也没有特别复杂。有两种函数组合的方式,一种是pipe,另一种是compose。前者从左向右组合函...

    Cristalven 评论0 收藏0
  • SegmentFault 技术周刊 Vol.16 - 浅入浅出 JavaScript 函数编程

    摘要:函数式编程,一看这个词,简直就是学院派的典范。所以这期周刊,我们就重点引入的函数式编程,浅入浅出,一窥函数式编程的思想,可能让你对编程语言的理解更加融会贯通一些。但从根本上来说,函数式编程就是关于如使用通用的可复用函数进行组合编程。 showImg(https://segmentfault.com/img/bVGQuc); 函数式编程(Functional Programming),一...

    csRyan 评论0 收藏0
  • JavaScript函数编程错误处理,强壮代码

    摘要:可当我们进行函数式编程时,这样的方式会遇到困难,难点在于如何停止。而在函数式编程中,数据在管道中流动,上一个函数的返回值会传给下一个函数,除非报错,事先写好的流程是停不下来的。 以下代码会用到函数组合函数compose,只要知道compose是干什么的就足够了,如果好奇具体的实现,可以看《JavaScript函数式编程之函数组合函数compose和pipe的实现》 在写命令式的代码时,...

    Yi_Zhi_Yu 评论0 收藏0

发表评论

0条评论

Jinkey

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<