scala 系列之 16scala 的柯理化

教程 潘牛 ⋅ 于 2021-07-08 22:54:53 ⋅ 1859 阅读

20 柯理化

​ 柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。

是把接受多个参数的函数变成接受一个参数的函数;

柯理化的两种表现形式:

以 加法函数为例:

​ def curring(x:Int)(y:Int) = x + y

​ def curring(x:Int) = (y:Int) => x + y

在柯理化形式的基础上,固定一个参数,传入一个参数

scala> def curring(x:Int)(y:Int) = x + y
curring: (x: Int)(y: Int)Int
scala> curring(4)(5)
res23: Int = 9
// 第一种方式
scala> val func1 = curring(5)_
func1: Int => Int = <function1>
scala> func1(4)
res25: Int = 9
// 第二种方式
scala> val func2 = (x:Int) => curring(x)(5)
func2: Int => Int = <function1>
scala> func2(4)
res26: Int = 9
scala> def curring(x:Int) = (y:Int) => x + y
curring: (x: Int)Int => Int
// 第三种方式
scala> val func3 = (x:Int) => curring(x)(5)
func3: Int => Int = <function1>
scala> func3(4)
res27: Int = 9

柯里化函数,配合implicit关键字使用

// 定义带有隐式参数的add方法
// implicit 修饰参数,代表该参数是隐式参数
scala> def add(a:Int)(implicit b:Int = 5) = a + b
add: (a: Int)(implicit b: Int)Int
// 直接传参
scala> add(4)(5)
res22: Int = 9
scala> add(4)(10)
res24: Int = 14
// 执行时,首先找当前环境是否有和隐式参数类型相同的隐式值,如果找到,用隐式值作为隐式参数
// 如果没找到,看隐式参数是否有默认值,如果有,使用默认值
// 如果还没找到,那就抛异常

// 当前环境没有和隐式参数类型相同的隐式值,隐式参数有默认值,使用默认值
// 4 + 5(默认值)
scala> add(4)
res25: Int = 9
// 定义隐式值
scala> implicit val b1:Int = 20
b1: Int = 20
// 当前环境有和隐式参数类型相同的隐式值,使用隐式值
// 4 + 20(隐式值)
scala> add(4)
res26: Int = 24
// 通过 implicitly[Int] 可提取出当前环境的隐式值并赋给变量
scala> val c:Int = implicitly[Int]
c: Int = 20
// 定义String类型隐式值
scala> implicit val b2:String = "aa"
b2: String = aa
scala> add(4)
res27: Int = 24
// 定义 Int类型隐式值, 当前环境有两个Int类型的隐式值
scala> implicit val b3:Int = 30
b3: Int = 30
// 由于当前环境有两个Int类型的隐式值,调用时不知道找哪个,所以报错
scala> add(4)
<console>:16: error: ambiguous implicit values:
 both value b1 of type => Int
 and value b3 of type => Int
 match expected type Int
       add(4)
          ^
// 由于当前环境已乱套,可通过退出重进解决
scala> :quit
C:\Users\My>scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_131).
Type in expressions for evaluation. Or try :help.
scala>

在开发环境中使用柯里化和implicit,切记不能在同一个类中使用

package util
// 隐式成员是单独放在一个地方,使用的时候引入
object MyPredef {
  // 定义隐式值1
  implicit val b1:Int = 10
  // 定义隐式值2
  implicit val b2:Int = 20
}

package day03
object CurringDemo {
  // 定义带有隐式参数的方法
  def add(a:Int)(implicit b:Int = 5) = a + b
  def main(args: Array[String]): Unit = {
    println(add(4)(1))
    println(add(4))
    // 引入隐式值之后,当前环境就有隐式值了
    import util.MyPredef.b1
    println(add(4))
// 当前环境有两个Int类型隐式值,报异常
//    import util.MyPredef.b2
//    println(add(4))
  }
}
版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-潘牛,http://hainiubl.com/topics/75751
成为第一个点赞的人吧 :bowtie:
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter