第6关:Scala函数柯里化和闭包

简介: 第6关:Scala函数柯里化和闭包

任务描述


本关任务:定义一个柯里化函数,求两个参数的最大公约数。


相关知识


为了完成本关任务,你需要掌握:


  1. 什么是柯里化;
  2. 什么是闭包。


函数柯里化


柯里化,俗称“部分求值”。一个柯里化函数首先是会接受一些参数,但是接受这些参数之后,该函数并不会立即求值,而是继续返回另一个函数,刚才传入的参数在函数形成的闭包中被保存起来。等到函数被真正需要求值的时候,之前传入的所有参数会被一次性用于求值。也就是说,柯里化是函数式编程的一种技巧,用于把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数。


实例:


首先我们定义一个函数:


def add(x:Int,y:Int)=x+y


那么我们应用的时候,应该是这样用:add(1,2)。


现在我们把这个函数变一下形:


def add(x:Int)(y:Int) = x + y


那么我们应用的时候,应该是这样用:add(1)(2),最后结果都一样是 3,这种方式(过程)就叫柯里化。


实现过程:


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


实质上最先演变成这样一个方法:


def add(x:Int)=(y:Int)=>x+y


那么这个函数是什么意思呢? 接收一个 x 为参数,返回一个匿名函数,该匿名函数的定义是:接收一个 Int 型参数 y,函数体为 x+y。现在我们来对这个方法进行调用。


val result = add(1)


返回一个result,那 result 的值应该是一个匿名函数:


(y:Int)=>1+y


所以为了得到结果,我们继续调用 result。


val sum = result(2)


最后打印出来的结果就是 3。


闭包


闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。

闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数。

如下面这段匿名的函数:


val multiplier = (i:Int) => i * 10


函数体内有一个变量 i,它作为函数的一个参数。如下面的另一段代码:


val multiplier = (i:Int) => i * factor


在 multiplier 中有两个变量:i 和 factor。其中的一个 i 是函数的形式参数,在 multiplier 函数被调用时,i 被赋予一个新的值。然而,factor 不是形式参数,而是自由变量,考虑下面代码:


var factor = 3
val multiplier = (i:Int) => i * factor


这里我们引入一个自由变量 factor,这个变量定义在函数外面。


这样定义的函数变量 multiplier 成为一个"闭包",因为它引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。


有意思的是,当这个自由变量发生变化时,Scala 的闭包能够捕获到这个变化,因此 Scala 的闭包捕获的是变量本身而不是当时变量的值。


4ab59e0c978b3b7cdcbde670de3df029.png


同样的,如果变量在闭包在发生变化,也会反映到函数外面定义的闭包的值。比如:


228fbd62dcc5eef52ee87857b5fbbcc3.png



可以看到在闭包中修改 sum 的值,其结果还是传递到闭包的外面。


编程要求


仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 间编写程序代码,计算两数的最大公约数。具体要求如下:


定义一个名为 gcd(a: Int)(b: Int) 的柯里化函数,返回值类型为 Int,计算 a、b 两数的最大公约数


测试说明


平台将使用测试集运行你编写的程序代码,若全部的运行结果正确,则通关。

测试输入:


  1. 33
  2. 58

预期输出:

  1. 1

测试输入:

  1. 10
  2. 2

预期输出:

  1. 2


开始你的任务吧,祝你成功!


参考答案


import scala.io.StdIn
object Scala函数柯里化和闭包 {
//    object Test {
        /********** Begin *********/
        def gcd(a: Int) (b: Int):  Int =
            if  (b == 0) a
            else gcd(b)( a % b)
        /********** End *********/
        def main(args: Array[String]): Unit = {
            val a = StdIn.readInt()
            val b = StdIn.readInt()
            println(gcd(a)(b))
        }
//    }
}
目录
相关文章
|
6月前
|
分布式计算 Scala Spark
Scala【集合常用方法和函数操作(下)】
Scala【集合常用方法和函数操作(下)】
|
6月前
|
分布式计算 Scala Spark
Scala 【集合常用方法和函数操作-上】
Scala 【集合常用方法和函数操作-上】
|
5月前
|
编译器 Scala
scala-柯里化、隐式转换、泛型、upperbound、viewbound、contextBound
scala-柯里化、隐式转换、泛型、upperbound、viewbound、contextBound
28 0
|
6月前
|
编译器 Scala
认识scala中的函数
认识scala中的函数
49 5
|
6月前
|
Scala
Scala函数和方法
Scala函数和方法
34 1
|
机器学习/深度学习 分布式计算 Java
Scala方法和函数
Scala方法和函数
99 0
|
Java 编译器 Shell
scala中的变量、方法、函数
Scala是一门多范式的编程语言,一种类似java的编程语言,是可扩展语言,并集成面向对象编程和函数式编程的各种特性的混合功能编程语言。 Scala被编译后在Java虚拟机上运行。
202 0
scala中的变量、方法、函数
|
大数据 Serverless Scala
大数据开发基础的编程语言的Scala的函数和闭包
Scala是一种支持函数式编程的编程语言,它具有强大的函数和闭包功能。本文将介绍Scala中函数和闭包的概念和用法,帮助开发者更好地理解和应用这门语言。
83 0
|
Java Scala
Scala快速入门-2-控制结构与函数
表达式有值,语句执行动作。 Scala中,几乎所有构造出来的语法结构都有值,不像Java中把表达式和语句(if语句)分为两类。 在这里if表示式有值。 代码块也有值,最后一个表达式就是值。 语句中,分号不是必需的。 函数式中不使用return。
|
SQL JSON 前端开发
Scala的面向对象与函数编程
Scala的面向对象与函数编程
Scala的面向对象与函数编程