scala Currying

函数是函数式编程的基本,在scala中你可以这样定义一个函数

val fun: Int => Int = i => i * i
val fun2 = (i: Int) => i * i
都达到了power(x,2)的想要结果

如果在repl中会显示,

val fun: Int => Int = i => i * i
scala> val fun: Int => Int = i => i * i
fun: Int => Int = <function1>


那么 <function1>是什么呢,其实是

trait Function1
{
     override def toString() = "<function1>"
}
实际上fun是Functon1的一个实例,在scala中,为我们定义了Funtion0~Function22 23个函数接口。

足够我们用了。


每次调用fun实际上是调用Function1.apply而已。

下面定义一个方法,

def mul(x: Int, y: Int) = x * y
引用baike 

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

尝试把mul 定义成柯里化的形式


scala  > def mulCurry(x:Int)(y:Int)=x*y
mulCurry: (x: Int)(y: Int)Int

scala> mul(2,3)
res3: Int = 6


scala> mulCurry(2)(3)
res5: Int = 6


柯里化和普通方法执行结果是一致的

 mulCurry(2)(3)实际上是依次调用两个普通函数(非柯里化函数),第一次调用使用一个参数 x,返回一个函数类型的值,第二次使用参数y调用这个函数类型的值。

实际上Curry也可表示为

def mulCurry(x: Int) = (y: Int) => x * y

scala> mulCurry(2)
res1: Int => Int = <function1>

返回的是一个函数类型的值 (val)输入第二个参数时再调用第一次生成的函数


scala> res1(2)
res2: Int = 4


柯里化常用在含隐式函数调用的地方,隐式函数下回分解

  1. curry化最大的意义在于把多个参数的function等价转化成多个单参数function的级联,这样所有的函数就都统一了,方便做lambda演算。 在scala里,curry化对类型推演也有帮助,scala的类型推演是局部的,在同一个参数列表中后面的参数不能借助前面的参数类型进行推演,curry化以后,放在两个参数列表里,后面一个参数列表里的参数可以借助前面一个参数列表里的参数类型进行推演。这就是为什么 foldLeft这种函数的定义都是curry的形式  
object CurryTest {
  //定义为柯里化函数时没有问题的,b的类型可以由a参与得出
  def method(a: A)(b: a.B) {

  }

  //参数列表的第二个参数,a没有定义,不能参与b的类型推断
  def method2(a: A, b: a.B /*a is not defined in a.B*/) {

  }

  def main(args: Array[String]) {

  }
}


下面一个例子摘自programming scala

import scala.util.control.NonFatal

// DeanW (Dec. 21, 2015): Refined the implementation and the usage
// example below to more clearly indicate the handling of the returned
// object of type T.
object manage {
  def apply[R <: { def close():Unit }, T](resource: => R)(f: R => T): T = {
    var res: Option[R] = None
    try {
      res = Some(resource)         // Only reference "resource" once!!
      f(res.get)                   // Return the T instance
    } catch {
      case NonFatal(ex) =>
        println(s"manage.apply(): Non fatal exception! $ex")
        throw ex
    } finally {
      if (res != None) {
        println(s"Closing resource...")
        res.get.close
      }
    }
  }
}

object TryCatchARM {
  /** Usage: scala rounding.TryCatch filename1 filename2 ... */
  def main(args: Array[String]) = {
    val sizes = args map (arg => returnFileLength(arg))
    println("Returned sizes: " + (sizes.mkString(", ")))
  }

  import scala.io.Source

  def returnFileLength(fileName: String): Int = {
    println()  // Add a blank line for legibility
    manage(Source.fromFile(fileName)) { source =>
      val size = source.getLines.size
      println(s"file $fileName has $size lines")
      if (size > 200) throw new RuntimeException(s"Big file: $fileName!")
      size
    }
  }
}
R可以认为是CloseAble的子类,利用柯里化技术,实现了java7的try with release编程。这是一个综合性例子,包含泛型,option,柯里化,call by name。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值