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 函数柯里化

柯里化指的是将原来接收两个参数的函数变成新的接受一个参数的函数过程,新的函数返回一个以原有第二个参数作为参数的函数。 例如:   def mul(x: Int, y: Int)= x * y 柯...
  • caoyang2256
  • caoyang2256
  • 2017年06月18日 17:44
  • 51

Scala高阶函数、闭包、​柯里化

一、高阶函数二、闭包三、柯里化四、Actor一、高阶函数scala的高阶函数:二、闭包scala 的闭包:函数里面引用外面类成员变量叫作闭包.例:三、柯里化四、Actorscala的多线程Actor是...
  • wenhui12345
  • wenhui12345
  • 2017年12月08日 00:00
  • 214

Scala 函数柯里化(Function currying)

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

深入理解scala的柯里化( currying or curry )以及其用处

百度百科定义: 柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。 例如: def add(x:In...
  • onwingsofsong
  • onwingsofsong
  • 2017年09月03日 16:42
  • 198

Scala 函数柯里化

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

Scala 函数柯里化(Currying)

柯丽华 ,其实很简单, 1、有一个函数,原来接受两个参数 2、现在我们将这个两个参数拆开 3、这样我们就得到了两个一个参数的函数了 4、这样我们调用的时候,就需要分别传入两个参...
  • qiezikuaichuan
  • qiezikuaichuan
  • 2016年07月23日 18:19
  • 405

scala 学习(十六)——闭包和柯里化

scala 学习(十六)——闭包和柯里化 下面是闭包和柯里化的例子程序: //变量不在作用域时函数仍然可以调用 object main{ def main(args:Array[Strin...
  • wild46cat
  • wild46cat
  • 2016年12月28日 15:19
  • 300

深入理解Scala中的函数式编程

核心内容: 1、Scala中函数的地位:一等公民 2、Scala中的匿名函数(函数字面量) 3、Scala中的高阶函数 4、Scala中的闭包 5、Scala中的部分应用函数 6、Scal...
  • a2011480169
  • a2011480169
  • 2016年11月13日 21:34
  • 3549

Scala 偏函数和偏应用函数

偏函数 偏函数是指仅定义了输入参数的子集的函数,如下图: 这个图显示的一个偏函数:f : X -> Y,该函数仅定义了输入参数X的子集1和3,没有包含2。 在Scala中的偏函数是通过特质Part...
  • qiruiduni
  • qiruiduni
  • 2015年07月16日 16:54
  • 1553

SCALA学习笔记(一)

变量 获取变量的值是一个耗时的工作时,可以考虑使用lazy var. lazy val forLater = someTimeConsumingOperation() scala> va...
  • bluishglc
  • bluishglc
  • 2015年02月27日 08:46
  • 23211
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:scala案例学习之Currying柯里化
举报原因:
原因补充:

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