1. 函数基础
1.1. 函数基本语法
package com.michael.learn.day02
object FunctionBasic {
def main(args: Array[String]): Unit = {
// 1. define a basic function and call the function
def f(arg: String):Unit = {
println(arg)
}
f("This is a string as the para")
}
}
1.2. 函数和方法的区别
(1)为完成某一功能的程序语句的集合,称为函数。
(2)类中的函数称之方法。
package com.michael.learn.day02
object DifferrenceBetweenFuncAndMethod {
// 1. The method can be override and overwrite
def main(): Unit = {
}
def main(args: Array[String]): Unit = {
// 2. You can declare any syntax in any syntax structure with Scala language
import java.util.Date
new Date()
// 3. Function can not be override and overwrite
def testFunction(): Unit = {
println("No para, No return value")
}
testFunction()
// def testFunction(name:String): Unit = { There is an error, cause function can not be override
// println(name)
// }
// testFunction("michael test")
// 3. You can declare nested functions in Scala language
def testFunction02():Unit = {
def testFunction03(name: String):Unit = {
println("The name you just input is : " + name)
}
testFunction03("michael")
}
testFunction02()
}
}
1.3. 函数定义
package com.michael.learn.day02
object FunctionPara {
def main(args: Array[String]): Unit = {
// 1. Function01: no para, no return
def test1():Unit = {
println("No para, No return value")
}
test1() // No para, No return value
// 2. Function02: No para, return a string
def test2(): String = {
return "No para but return value"
}
println(test2()) // No para but return value
// 3. Function03: Para, no return
def test3(s:String): Unit = {
println("The input string is : "+s)
}
test3("michael test") // The input string is : michael test
// 4. Function04: Para, return value
def test4(s:String): String = {
return s
}
println(test4("input a string and get it back")) // input a string and get it back
// 5. Function05: multiple paras, no return
def test5(name:String, age:Int): Unit = {
println(s"$name, $age")
}
test5("michael", 18) // michael, 18
}
}
1.4. 函数参数
package com.michael.learn.day02
object FunctionPara {
def main(args: Array[String]): Unit = {
// 1. variable parameter
def test(str:String*):Unit = {
println(str)
}
test("hello", "scala") // WrappedArray(hello, scala)
test() // List()
// 2. The variable para is usually placed last if there are more than one para in the para list
def test2(first:String, multiple:String*):Unit = {
println(first + ", " + multiple)
}
test2("first para", "second", "third") // first para, WrappedArray(second, third)
// 3. Default value of para
def test3(name:String = "first", age:Int = 15):Unit = {
println(s"$name, $age")
}
test3("michael", 18) // michael, 18
test3() // first, 15
test3(age=19) // first, 19
}
}
1.5. 函数置简原则
函数至简原则:能省则省
1.5.1. 至简原则细节
- return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
- 如果函数体只有一行代码,可以省略花括号
- 返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
- 如果有 return,则不能省略返回值类型,必须指定
- 如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
- Scala 如果期望是无返回值类型,可以省略等号
- 如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
- 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
- 如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
1.5.2. 代码实例
package com.michael.learn.day02
object FunctionMinimizationPrinciple {
def main(args: Array[String]): Unit = {
// Standard function declare
def f(s:String):String = {
return s + "function return"
}
println(f("the standard function ")) // the standard function function return
// 1. return can be omitted in Scala
def f1(s:String):String = {
s + "return is omitted"
}
println(f1("the function without return ")) // the function without return return is omitted
// 2. {} can be omitted if there is only one line code
def f2(s:String):String = s + "{} is omitted"
println(f2("omit brace")) // omit brace{} is omitted
// 3. : and return_type can be omitted if the return value type can be inferred
def f3(s:String) = s + "return type is omitted"
println(f3("omit return type")) // omit return typereturn type is omitted
// 4. return type can not be omitted if there is a return
def f4(s:String):String = return s + "{} is omitted"
println(f4("Don't omit return value")) // Don't omit return value{} is omitted
// 5. The return does not work if return type is Unit
def f5(s:String):Unit = return s + "return does not work"
println(f5("Use unit")) // ()
// 6. = can be omitted if there is no return value
def f6() {"= is omitted"}
println(f6()) // ()
// 7. () can be omitted when call the func if there is no para when defined with para list
def f7():String = {"no para"}
println(f7()) // no para
println(f7) // no para
// 8. () must be omitted when call the func if defined without para list
def f8:String = {"no para list"}
println(f8) // no para list
// println(f8()) // error
// 9. def can be omitted if only care about logic process
def f9 = (x:String) => {println(x + "new function define way with =>")}
def f10(f:String => Unit) = {
f("")
}
f10(f9) // new function define way with =>
println(f10((x:String) => println("def is omitted"))) // def is omitted
}
}
2.函数高级
2.1. 高阶函数
package com.michael.learn.day02
object AdvancedFunction {
def main(args: Array[String]): Unit = {
// 1. call func
foo() // foo is called............
// 2. call foo and give the return value to the variable f
val f = foo() // foo is called............
println(f) // return a string
// 3. passing the func foo as a whole to the variable f1 is the same as passing the func foo as a whole
val f1 = foo _
foo() // foo is called............
f1() // foo is called............
// 4. The _ can be omitted if the return type is specified
val f2:() => String = foo
f2() // foo is called............
// 5. func can be the para of another func
def f3(foo2:(Int, Int) => Int):Int = {
foo2(2, 4)
}
def add(a:Int, b:Int):Int = a + b
println(f3(add _))
println(f3(add))
// 6. func can be the return value
def foo3() = {
def foo4() = {
println("the inner func is called")
}
foo4 _
}
val f4 = foo3()
f4() // the inner func is called
foo3()() // the inner func is called
}
// define func
def foo():String = {
println("foo is called............")
return "return a string"
}
}
2.2. 匿名函数
没有名字的函数就是匿名函数。
(x:Int)=>{函数体} x:表示输入参数类型;Int:表示输入参数类型;函数体:表示具体代码逻辑
2.2.2. 匿名函数基础推导
package com.michael.learn.day02
object AnonymousFunc {
def main(args: Array[String]): Unit = {
// 1. anonymous func usage
def operation(arr: Array[Int], op:Int => Int) = {
for (elem <- arr) yield op(elem)
}
def op(ele:Int):Int = {
ele + 1
}
val arr = operation(Array(1, 2, 3, 4), op)
println(arr.mkString(",")) // 2,3,4,5
// 1.1. anonymous func01
val arr1 = operation(Array(1, 2, 3, 4), (ele:Int) => {ele+1})
println(arr1.mkString(",")) // 2,3,4,5
// 1.2. anonymous func02 : omit para type
val arr2 = operation(Array(1, 2, 3, 4), (ele) => ele + 1)
println(arr2.mkString(",")) // 2,3,4,5
// 1.3. anonymous func03 : omit ()
val arr3 = operation(Array(1, 2, 3, 4), ele => ele + 1)
println(arr3.mkString(",")) // 2,3,4,5
// 1.4. anonymous func04 : omit {}
val arr4 = operation(Array(1, 2, 3, 4), (ele) => ele + 1)
println(arr4.mkString(",")) // 2,3,4,5
// 1.5. anonymous func05 : omit the argument and the following argument can be replaced by _ if the argument appears only once
val arr5 = operation(Array(1, 2, 3, 4), _ + 1)
println(arr5.mkString(",")) // 2,3,4,5
// 2. anonymous func usage02
def calculator(a:Int, b:Int, op:(Int, Int) => Int):Int = {
op(a, b)
}
println(calculator(2, 3, (x:Int, y:Int) => {x + y})) // 5
println(calculator(2, 3, (x:Int, y:Int) => x + y)) // 5
println(calculator(2, 3, (x, y) => x + y)) // 5
println(calculator(2, 3, _ + _)) // 5
}
}
2.2.2. 匿名函数的实例
package com.michael.learn.day02
import scala.collection.mutable.ArrayBuffer
object AdvancedFuncInstance {
def main(args: Array[String]): Unit = {
// 1. map
def map(arr:Array[Int], op: Int => Int) = {
for(ele <- arr) yield op(ele)
}
val arr = map(Array(1, 2, 3, 4), x => x*x)
println(arr.mkString(",")) // 1,4,9,16
// 2. filter
def filter(arr:Array[Int], op:Int => Boolean) = {
var arr1:ArrayBuffer[Int] = ArrayBuffer[Int]()
for(ele <- arr if op(ele)){
arr1.append(ele)
}
arr1.toArray
}
val arr2 = filter(Array(1, 2, 3, 4), _ % 2 == 1)
println(arr2.mkString(",")) // 1,3
// 3. reduce
def reduce(arr:Array[Int], op: (Int, Int) => Int) = {
var init:Int = arr(0)
for(ele <- 1 to arr.length){
init = op(init,ele)
}
init
}
val arr3 = reduce(Array(1, 2, 3, 4), _ * _)
println(arr3) // 24
}
}
2.3. 函数柯里化&闭包
闭包: 如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包
函数柯里化: 把一个参数列表的多个参数,变成多个参数列表。
package com.michael.learn.day02
object FuncClosure {
def main(args: Array[String]): Unit = {
// 1. closure
def f1() = {
var a:Int = 10
def f2(b:Int) = {
a + b
}
f2 _
}
// 在调用时,f1 函数执行完毕后,局部变量 a 应该随着栈空间释放掉
// 但是在此处,变量 a 其实并没有释放,而是包含在了 f2 函数的内部,形成了闭合的效果
val f = f1()
println(f(3)) // 13
println(f1()(3)) // 13
// 2. func currying
var c:Int = 10
def f4()(b:Int)= {
c + b
}
println(f4()(3)) // 13
}
}
2.4. 递归
一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用
package com.michael.learn.day02
object Recursion {
def main(args: Array[String]): Unit = {
println(test(5)) // 120
}
// scala 中的递归必须声明函数返回值类型
def test(i:Int): Int ={
if (i == 1){
1
}else {
i * test(i -1)
}
}
}
2.5. 控制抽象
2.5.1. 值调用:把计算后的值传递过去
2.5.2. 名调用:把代码传递过去
package com.michael.learn.day02
object ControlAbstract {
def main(args: Array[String]): Unit = {
// 1. call func value
def f = () => {
println("f is called")
10
}
foo(f())
// 2. call func name
foo2(f())
// 3. implement your own while loop
var i :Int = 1
michalWhile(i <= 10){
println(i)
i +=1
}
}
def foo(a:Int):Unit = {
println(a)
}
def foo2(a: => Int):Unit = {
println(a)
}
def michalWhile(condition: => Boolean)(op: => Unit):Unit = {
if (condition){
op
michalWhile(condition)(op)
}
}
}
2.6. 惰性加载
当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数。
package com.michael.learn.day02
object LazyLoadFunc {
def main(args: Array[String]): Unit = {
lazy val res = sum(100, 3)
println("========= separator ============")
println("res" + res)
/* console result
========= separator ============
sum func is called
res103
*/
}
def sum(a:Int, b:Int):Int = {
println("sum func is called")
a + b
}
}
注意:lazy 不能修饰 var 类型的变量