控制抽象
1. 减少代码重复
object FunDemo {
private val filesHere = new java.io.File(".").listFiles()
//1. 查询后缀名为 .scala的文件
def fileEndWith(query: String): Array[File] = {
for (file <- filesHere; if file.getName().endsWith(query))
yield file
}
//2. 查询文件名包含 phb 的文件
def fileContains(query: String): Array[File] = {
for (file <- filesHere; if file.getName().contains(query))
yield file
}
//3. 查询文件名 符合正则表达式的名字
def fileRegex(query: String): Array[File] = {
for (file <- filesHere; if file.getName().matches(query))
yield file
}
//4. 前三个方法重复, 使用高阶函数抽象
def fileMatch(query: String, matcher: (String, String) => Boolean): Array[File] = {
for (file <- filesHere; if matcher(file.getName, query))
yield file
}
//重构前三个方法
def fileEndWith2(query: String): Array[File] = {
fileMatch(query, _.endsWith(_)) //这里使用的不是闭包,就是占位符
//函数字面量 :_.endsWith(_) 等同于
//(filename: String, query: String) => filename.endsWith(query)
}
def fileContains2(query: String): Array[File] = {
fileMatch(query, _.contains(_))
}
def fileRegex2(query: String): Array[File] = {
fileMatch(query, _.matches(_))
}
//5. 进一步简化代码
private def fileMatch2(matcher: String => Boolean): Array[File] = {
for (file <- filesHere; if matcher(file.getName()))
yield file
}
//进一步重构前三个方法
def fileEndWith3(query: String): Array[File] = {
fileMatch2(_.endsWith(query)) //这里使用是闭包,自由变量为query
}
def fileContains3(query: String): Array[File] = {
fileMatch2(_.contains(query))
}
def fileRegex3(query: String): Array[File] = {
fileMatch2(_.matches(query))
}
def main(args: Array[String]): Unit = {
//高阶函数: 那些接收函数作为参数的函数
}
}
object FunDemo {
private val arr = List(-11, -10, -5, 0, 5, 10)
def containNeg(nums: List[Int]): Boolean ={
var exists = false
for (elem <- nums) {
if(elem < 0)
exists = true
}
exists
}
def containPositive(nums: List[Int]): Boolean ={
var exists = false
for (elem <- nums) {
if(elem > 0)
exists = true
}
exists
}
def containOdd(nums: List[Int]): Boolean ={
var exists = false
for (elem <- nums) {
if(elem %2 == 1)
exists = true
}
exists
}
def containEven(nums: List[Int]): Boolean ={
var exists = false
for (elem <- nums) {
if(elem %2 == 0)
exists = true
}
exists
}
}
//----------简化之后如下----------
object FunDemo {
private val arr = List(-11, -10, -5, 0, 5, 10)
def containNeg(nums: List[Int]): Boolean = {
contain(nums, _ < 0)
}
def containPositive(nums: List[Int]): Boolean = {
contain(nums, _ > 0)
}
def containOdd(nums: List[Int]): Boolean = {
contain(nums, _ / 2 == 1)
}
def containEven(nums: List[Int]): Boolean = {
//val matcher = (ele: Int) => (ele/2 == 0)
//contain(nums, matcher)
//contain(nums, (ele: Int) => (ele / 2 == 0))
//contain(nums, ele => ele / 2 == 0)
contain(nums, _ / 2 == 0)
}
def contain(nums: List[Int], matcher: Int => Boolean): Boolean = {
var exists = false
for (elem <- nums) {
if (matcher(elem))
exists = true
}
exists
}
def containNeg2(nums: List[Int]): Boolean = contain(nums, _ < 0)
def containPositive2(nums: List[Int]): Boolean = contain(nums, _ > 0)
def containOdd2(nums: List[Int]): Boolean = contain(nums, _ / 2 == 1)
def containEven2(nums: List[Int]): Boolean = contain(nums, _ / 2 == 0)
}
//-------------集合本省的迭代------------------
object FunDemo {
def containNeg(nums: List[Int]): Boolean = nums.exists(_ < 0)
def containPositive(nums: List[Int]): Boolean = nums.exists(_ > 0)
def containOdd(nums: List[Int]): Boolean = nums.exists(_ % 2 == 0)
def containEven(nums: List[Int]): Boolean = nums.exists(_ % 2 == 1)
}
//柯里化和普通函数
object FunDemo {
def sum(a: Int, b: Int) = a + b
def curriedSum(a: Int)(b: Int) = a + b
def main(args: Array[String]): Unit = {
/**
* 这里调用 柯里化函数
* 实际上连着做了两次传统的函数调用
*/
val intToInt = curriedSum(1)(2)
println(intToInt)
//1. 获取柯里化函数第一次调用的函数值, 使用占位符
val one = curriedSum(1)_
println(one(3))
}
}
//编写新的控制结构
def twice(op: Double => Double, x: Double): Double = op(op(x))
def main(args: Array[String]): Unit = {
val op = (x: Double) => x + 5
println(twice(op, 2))
println(twice((x: Double) => x + 5, 2))
println(twice(x => x + 5, 2))
println(twice(_ + 5, 2)) // 调用
}
//控制抽象
def withPrintWriter(file: File, op: PrintWriter => Unit): Unit = {
val writer = new PrintWriter(file)
try {
op(writer)
} finally {
writer.close()
}
}
def main(args: Array[String]): Unit = {
//调用
withPrintWriter(new File("data.txt"), out => out.println(new java.util.Date()))
println {
"aaa"
} //花括号替代圆括号,看起来更像是内嵌的控制结构
}
//使用柯里化改造
def withPrintWriter(file: File)(op: PrintWriter => Unit): Unit = {
val writer = new PrintWriter(file)
try {
op(writer)
} finally {
writer.close()
}
}
//调用
def main(args: Array[String]): Unit = {
val op = (out: PrintWriter) => out.println(new java.util.Date())
withPrintWriter(new File("data.txt")){
op
}
withPrintWriter(new File("data.txt")){
//在花括号中编写函数字面量
out => out.println(new java.util.Date())
}
}
//传名参数
def main(args: Array[String]): Unit = {
myAssert(() => 5 > 3) //调用方式很奇怪
}
var assert = true
def myAssert(predicate: () => Boolean): Unit = {
if (assert && !predicate())
throw new AssertionError
}
//修改为传名参数:
//定义格式:=> Boolean
def main(args: Array[String]): Unit = {
myAssert(5 > 3) //调用方式很奇怪
}
var assert = true
def myAssert(predicate: => Boolean): Unit = {
if (assert && !predicate)
throw new AssertionError
}
/**
* def myAssert(predicate: => Boolean): Unit
* 和
* def myAssert2(predicate: Boolean): Unit 区别:
*
* myAssert2: 先计算predicate,再做函数调用
* myAssert:predicate: => Boolean 先转换为一个函数值,调用函数值的apply方法,计算表达式的值,然后再函数调用
*
*/
def myAssert(predicate: => Boolean): Unit = {
if (assert && !predicate)
throw new AssertionError
}
def myAssert2(predicate: Boolean): Unit = {
if (assert && !predicate)
throw new AssertionError
}
def main(args: Array[String]): Unit = {
myAssert(5>3) //不会报错
myAssert2(2/0==0) // 报错
}
网友评论