scala案例学习之Currying柯里化

转载 2016年08月29日 22:26:52
【写在前面】
     由于之前工作的一些特殊情况,加上在比较多使用知识管理软件(为知/有道云笔记等)后,就越来越少写博客,但在生活工作却总感觉缺少了点东西,蓦然回首发现原来是“丢失了”"学习写作"的修炼心。故有必要重新治理一下博客,以rscala.com记录、分享自己在IT技术自我修炼与窥探历程。

一、初识Currying柯里化
  柯里化(Currying)技术 Christopher Strachey 以逻辑学家 Haskell Curry 命名的(尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的)。它是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。

  简单理解就是改变函数的表达形式但其功能特性不变,这对于第一次接触柯里化的人来讲,这样的一个技术貌似有点“鸡肋”,但如果你有丰富的JS编程经验的话,相信就一定会感受到柯里化其实是具有很高的实用性的。无论是在提高适用性还是在延迟执行或者固定易变因素等方面,柯里化技术都发挥着重要的作用。

二、从案例角度学习scala柯里化
   还是老观点——无论是修炼新技术还是旧理论,结合小案例理解学习,才是最有效的方法。下面将通过几个例子来学习scala柯里化。
    2.1、从2个整数相乘运算的函数来揭开柯里化的神秘面纱
    在scala中定义2个整数相乘运算的函数是非常简单的,具体如下:
    def multiplie2par(x:Int,y:Int)=x*y
    使用柯里化技术可以将上述2个整数的乘法函数改修为接受一个参数的函数,只是该函数返回是一个以原有第二个参数为参数的函数。
    def multiplie1par(x:Int)=(y:Int)=>x*y
【ps说明:multiplie1par(x:Int)为接收一个参数的新等价函数,(y:Int)=>x*y则是新等价函数的返回体,它本身就是一个函数(严格来说应该是一个匿名函数),参数为除等价新函数的参数外原函数剩余的参数。
    上述使用柯里化技术得到等价新函数,在scala语言中看起来还不是很简洁,在scala中可以进一步简化为:
     def multiplie1par1(x:Int)(y:Int)=x*y
    编译运行的结果如下:
    
同样对于三个整数乘法的函数在scala中由于有柯里化的存在,自然有多种功能等价的函数定义形式,如以下四种函数都是实现了三个整数乘法功能,只不过调用不同形式参数过程略有不同,直接参入三个参数的一步到位就可以得到运算结果,而传入1或者2个参数的需要分步骤再传入第2/3或者第3个参数才能求出三个整数相乘的结果,很好地体现了延迟执行或者固定易变因素等方面能力
    def multiplie3par(x:Int,y:Int,z:Int)=x*y*z
    def multiplie3par1(x:Int)=(y:Int,z:Int)=>x*y*z
    def multiplie3par2(x:Int)(y:Int)(z:Int)=x*y*z
    def multiplie3par3(x:Int)(y:Int)=(z:Int)=>x*y*z
编译执行的结果都是一样

    2.2、scala中柯里化的另一种典型案例——correspondsf方法的柯里化应用
    在scala中corresponds方法能使得两个序列按照一定的条件进行比较,该方法其实也是经过柯里化参数的。在scala的API中该方法定义如下:在方法签名描述中有两个参数,that序列和p函数,其中p函数有两个参数,第二个参数类型是与that序列一致的。应用柯里化,我们可以省去第二个参数中B的类型,因为从that序列中推断出B的类型。
    def corresponds[B](that: GenSeq[B])(p: (T, B) ⇒ Boolean): Boolean
    因此假如有字符串类型序列a和字符串序列b,我们可以使用a. corresponds(b)(_. equalsIgnoreCase(_))来判断两个字符串序列在不区分大小的情况是否一致,这就为编程带来了“魔法般”的灵活性。   

三、总结柯里化的作用

   3.1、柯里化技术在提高适用性还是在延迟执行或者固定易变因素等方面有着重要重要的作用,加上scala语言本身就是推崇简洁编码,使得同样功能的函数在定义与转换的时候会更加灵活多样。另外在Spark的源码中有大量运用scala柯里化技术的情况,需要掌握好该技术才能看得懂相关的源代码。
  3.2、在scala柯里化中,闭包也发挥着重要的作用。所谓的闭包就是变量出了函数的定义域外在其他代码块还能其作用,这样的情况称之为闭包。就上述讨论的案例而言,如果没有闭包作用,那么转换后函数其实返回的匿名函数是无法在与第一个参数x相关结合的,自然也就无法保证其所实现的功能是跟原来一致的。

本文出自AiTi修炼|大技术窥探 ,转载时请注明出处与连接。

相关文章推荐

Scala 函数柯里化

Scala 函数柯里化介绍。
  • yyywyr
  • yyywyr
  • 2015年12月13日 12:10
  • 3207

scala柯里化函数

柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数, 并且返回接受余下的参数而且返回结果的新函数的技术。柯里化其实本身是固定一个可以预期的参数,并返回一个特定的函数,处理...

scala akka 修炼之路6(scala函数式柯里化风格应用场景分析)

scala的函数式和面向对象风格,可以让想想随时发生;如果你是画家,使用scala写出来的代码更像一幅充满诗意的风景画。如果你是作家,写出的将是一个扣人心弦的跌宕起伏的大篇。scala给不同类型的程序...

Scala柯里化和反柯里化

名词解释 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。 柯里化举例说明def...

使用java模拟scala函数式编程将函数作为参数传入方法中

需求:将一个list集合传入一个方法中,同时传入一个函数,根据传入函数的不同对集合做不同的处理 方法:定义一个接口,并定义一个方法option,测试中调用一个方法传入的参数是list和函数,...

Scala教程(十九)Scala界面GUI编程

Scala开发图形用户界面(GUI)的应用程序基于一个Scala库,该类库提供对Java的Swing框架的GUI类访问。该类库和它的下层的Swing类很像,隐藏了大部分的复杂度,使Scala开发图形用...
  • yuan_xw
  • yuan_xw
  • 2015年11月06日 17:02
  • 2556

Scala 函数柯里化(Function currying)

部分应用的函数 和其他遵循函数式编程范式的语言一样,Scala 允许部分应用一个函数。 调用一个函数时,不是把函数需要的所有参数都传递给它,而是仅仅传递一部分,其他参数留空; 这样会生成一个新的函数...

Scala Learning(4): Currying柯里化的推演

本文展示加法和乘法的两个例子,最后使用MapReduce的思想把两者统一成一个带Currying的表达形式。从high-order functions推演到Currying原始方法def sum(f:...

对Javascript柯里化currying的理解

对于currying,在《Javascript高级程序设计(第3版)》的604页第22.1.5节有一句言简意赅的解释:“它用于创建已经设置好了一个或多个参数的函数”。要更好的学习和理解currying...

currying in javascript-js柯里化

柯里化是指将一个多参数的函数转化成更少参数的函数,专业解释看维基百科。柯里化实现是通过把参数列表中的某些参数绑定到首先被调用的函数里,这样这些参数就附加到下一次的调用里。这个有个表现柯里化样子的例子:...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:scala案例学习之Currying柯里化
举报原因:
原因补充:

(最多只允许输入30个字)