Scala作为函数式语言,函数自然是头等公民…
一个接收函数作为参数的函数称为高阶函数
比如定义如下:
defvalueAtOneQuarter(f: (Double) => Double) = f(0.25)
这个函数接收一个参数为Double返回值为Double的函数作为参数。
高阶函数还可以是返回一个函数作为参数的函数,如下
defmulBy(factor : Double) = (x : Double) => factor * x
valquintuple = mulBy(5)
quintuple(20)
mulBy的类型为:
(Double)=> ((Double) => Double)
这里的高阶函数看上有点蛋疼,他的用处在于可以将一个多参数的函数转换成几个一元函数。(后面知道这种叫闭包,并且也是柯里化的结果)
调用valueAtOneQuarter函数时,如果传入的参数是匿名的,调用可以是以下方式:
valueAtOneQuarter((x: Double) => 3 * x)
由于类型推断的存在以上调用的最终简化版是
valueAtOneQuarter(3* _)
Scala中的控制抽象是一个比较复杂的概念,如下函数在线程中执行某段代码:
defrunInThread(block : () => Unit){
new Thread{
Override def run() { block() }
}.start()
}
上面代码runInThread 函数的参数是一个无参数无返回值的函数
调用代码如下
runInThread
看上去代码并不美观(()=> ),这里scala允许一种换名调用表示法: 在参数声明和调用该函数参数的地方省略() , 但是在声明的地方保留 => ,如下:
defrunInThread(block : => Unit){
new Thread{
Override def run() { block() }
}.start()
}
现在调用可以变成下面这样:
runInThread{
println("Hi")
Thread.sleep(10000)
println("Bye")
}
看看下面神奇代码:
defuntil( condition : => Boolean)(block : => Unit){
If(!condition){
block
until( condition)(block)
}
}
来看看调用:
var x =10
until (x== 0){
x -= 1
println(x)
}
以上代码类似于while循环,只不过把条件反过来了,一个函数定义利用递归、柯里化、以及换名调用就实现了一个自定义版本的while
package demo
/**
* @author Administrator
*/
object ScalaHighMethod {
def main(args: Array[String]): Unit = {
var x = 10
until(x == 0) {
x -= 1
println(x)
}
val r = values(-5, 5, x => x * x)
r.foreach(println)
r.foreach(p => println(p._1 + "->" + p._2))
val ar = Array(4, 6, 9, 12, 45, 2, 5, 14, 12, 46)
val maxV = ar.reduceLeft((v1: Int, v2: Int) => { if (v1 > v2) v1 else v2 })
val maxV2 = ar.reduceLeft(_ max _)
println(maxV)
val fun = (x: Int) => (1 to x) reduceLeft (_ * _)
val fun2 = (x: Int) => (1 to x).foldLeft(1)(_ * _)
println(fun(4))
println(fun2(4))
println(largest(x => 10 * x - x * x, 1 to 10))
println(largest2(x => 10 * x - x * x, 1 to 10))
val pairs = (1 to 10) zip (11 to 20)
pairs map (adToPair(_ + _)) foreach {
println(_)
}
//原集合并没有变化
pairs foreach {
println(_)
}
println(adToPair(_ * _)(6, 7))
val strs = Array("yang", "ming", "wei")
val ints = Array(4, 4, 3)
println(corresponds(strs, ints, _.length == _))
val vc = 10
unless(vc > 10) {
println(vc)
}
}
def corresponds(arg1: Seq[String], agr2: Seq[Int], fun: (String, Int) => Boolean) = {
arg1.corresponds(agr2)(fun)
}
def adToPair(p: (Int, Int) => Int) = {
(arg: Tuple2[Int, Int]) => p(arg._1, arg._2)
}
def largest(fun: (Int) => Int, input: Seq[Int]) = {
input map (fun) max
}
def largest2(fun: (Int) => Int, input: Seq[Int]) = {
input maxBy { fun }
}
def until(condition: => Boolean)(block: => Unit) {
if (!condition) {
block
until(condition)(block)
}
}
def unless(condition: => Boolean)(block: => Unit) {
if (!condition) {
block
}
}
def values(low: Int, high: Int, fun: (Int) => Int) = {
var ab = Map[Int, Int]()
for (i <- low to high) {
ab += (i -> fun(i))
}
ab
}
}