《快学Scala》(英文版:《Scala for the Impatient》),代码已传github:
https://github.com/vernonzheng/scala-for-the-Impatient
书为第一版。scala为2.11.4,jdk1.7.45,操作系统Mac OS X Yosemite 10.10.1。
第十二章 高阶函数
12.1
编写函数values(fun:(Int)=>Int,low:Int,high:Int),该函数输出一个集合,对应给定区间内给定函数的输入和输出。比如,values(x=>x*x,-5,5)应该产出一个对偶的集合(-5,25),(-4,16),(-3,9),…,(5,25)
1 2 3 4 5 6 7 8 9
| def values(fun:(Int)=>Int,low:Int,high:Int) ={ var array = List[(Int,Int)]() low to high foreach { x => array = (x, fun(x)) :: array } array } println(values(x => x * x, -5, 5).mkString)
|
12.2
如何用reduceLeft得到数组中的最大元素?
1 2
| val arr = Array(1,333,4,6,4,4,9,32,6,9,0,2) print(arr.reduceLeft((l,r)=>if(l>=r) l else r))
|
12.3
用to和reduceLeft实现阶乘函数,不得使用循环或递归
1 2 3
| def factorial(n:Int): Unit ={ 1 to n reduceLeft(_ * _) }
|
12.4
前一个实现需要处理一个特殊情况,即n<1的情况。展示如何用foldLeft来避免这个需要。
1 2 3 4
| def factorial(n:Int) = (1 to n).foldLeft(1)(_ * _) factorial(-3) factorial(3)
|
12.5
编写函数largest(fun:(Int)=>Int,inputs:Seq[Int]),输出在给定输入序列中给定函数的最大值。举例来说,largest(x=>10x-xx,1 to 10)应该返回25.不得使用循环或递归
1 2 3 4 5 6
| def largest1(fun:(Int)=>Int, inputs:Seq[Int]) = inputs.foldLeft(1)((a,b)=> if(fun(b)>a) fun(b) else a) def largest2(fun:(Int)=>Int, inputs:Seq[Int]) = inputs.map(fun(_)).max println(largest1(x => 10 * x - x * x, 1 to 10)) println(largest2(x => 10 * x - x * x, 1 to 10))
|
12.6
修改前一个函数,返回最大的输出对应的输入。举例来说,largestAt(fun:(Int)=>Int,inputs:Seq[Int])应该返回5。不得使用循环或递归
1 2 3 4 5 6
| def largestAt1(fun:(Int)=>Int, inputs:Seq[Int]) = inputs.reduce((a,b)=> if(fun(b)>fun(a)) b else a) def largestAt2(fun: (Int) => Int, inputs: Seq[Int]) = inputs.map(x => (x, fun(x))).reduceLeft((x,y) => if (x._2 > y._2) x else y)._1 println(largestAt1(x => 10 * x - x * x, 1 to 10)) println(largestAt2(x => 10 * x - x * x, 1 to 10))
|
12.7
要得到一个序列的对偶很容易,比如:
val pairs = (1 to 10) zip (11 to 20)
假定你想要对这个序列做某中操作—比如,给对偶中的值求和,但是你不能直接使用:
pairs.map( + )
函数 + 接受两个Int作为参数,而不是(Int,Int)对偶。编写函数adjustToPair,该函数接受一个类型为(Int,Int)=>Int的函数作为参数,并返回一个等效的, 可以以对偶作为参数的函数。举例来说就是:adjustToPair( * )((6,7))应得到42。然后用这个函数通过map计算出各个对偶的元素之和
1 2 3 4 5 6 7 8 9 10
| def ajustToPair(fun: (Int, Int) => Int) = (x: (Int, Int)) => fun(x._1, x._2) val x = ajustToPair(_ * _)((6, 7)) println(x) val pairs = (1 to 10) zip (11 to 20) println(pairs) val y = pairs.map(ajustToPair(_ + _)) println(y)
|
12.8
在12.8节中,你看到了用于两组字符串数组的corresponds方法。做出一个对该方法的调用,让它帮我们判断某个字符串数组里的所有元素的长度是否和某个给定的整数数组相对应
1 2 3 4 5 6
| val a = Array("asd","df","abcd") val b = Array(3,2,4) val c = Array(3,2,1) println(a.corresponds(b)(_.length == _)) println(a.corresponds(c)(_.length == _))
|
12.9
不使用柯里化实现corresponds。然后尝试从前一个练习的代码来调用。你遇到了什么问题?
没有柯里化则不能使用前一个练习里的代码方式来调用
12.10
实现一个unless控制抽象,工作机制类似if,但条件是反过来的。第一个参数需要是换名调用的参数吗?你需要柯里化吗?
1 2 3
| def unless(condition: => Boolean)(block: => Unit) { if (!condition) { block } } unless (0 > 1) { println("Unless!") }
|
需要换名和柯里化
参考:
《快学Scala》:http://book.douban.com/subject/19971952/
(转载本站文章请注明作者和出处 Vernon Zheng(郑雪峰) – vernonzheng.com ,请勿用于任何商业用途)