Scala中的柯里化

1、初识Currying柯里化

  柯里化(Currying)技术 Christopher Strachey 以逻辑学家 Haskell Curry 命名的(尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的)。它是 把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,而且返回接受余下的参数且返回结果的新函数的技术。
 
  简单理解就是改变函数的表达形式但其功能特性不变,这对于第一次接触柯里化的人来说,这样的一个技术貌似有点“鸡肋”,但若是你有丰富的JS编程经验的话,相信就必定会感觉到柯里化实际上是具备很高的实用性的。不管是在提升适用性仍是在延迟执行或者固定易变因素等方面,柯里化技术都发挥着重要的做用。
 

2、从案例角度学习scala柯里化

   仍是老观点——不管是修炼新技术仍是旧理论,结合小案例理解学习,才是最有效的方法。下面将经过几个例子来学习scala柯里化。
    2.一、从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.二、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、总结柯里化的做用

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