Scala学习手册(Learning Scala)第四章:函数


Scala学习手册(Learning Scala)第4四章:函数

你好,朋友


1、无输入的函数

scala> def hi = "hi"
hi: String

2、有输入的函数

定义:

def <identifier>(<identifier>:<type>[,...]):<type> = <expression>

scala> def multiplier(x:Int,y:Int):Int = {x * y}
multiplier: (x: Int, y: Int)Int
scala> multiplier(6,7)
res6: Int = 42

3、过程

指没有返回值的函数,通常以一个语句(println()调用)结尾的函数也是过程。

scala> def log(d:Double) = println(f"Got value $d%.2f")
log: (d: Double)Unit
scala> log(3.4332)
Got value 3.43

4、使用表达式块调用函数

使用一个参数调用函数时,可以利用一个用大括号包围的表达式块发送参数,而不是用小括号包围值。通过使用表达式块调用函数,可以完成一些计算和其他动作,然后利用这个块的返回调用函数。

scala> def formatEuro(amt:Double) = f" $amt%.2f"
formatEuro: (amt: Double)String
scala> formatEuro(3.4567323)
res13: String = " 3.46"
scala> formatEuro{val rate = 1.32;0.345+0.7432+rate*5.32}
res15: String = " 8.11"

5、递归(recursive)

递归函数就调用函数自身的函数。

scala> def power(x:Int,n:Int):Long = {
| if(n >= 1) x*power(x,n-1)
| else 1
| }
power: (x: Int, n: Int)Long
scala> power(10,1)
res16: Long = 10
scala> power(1,10)
res17: Long = 1
scala> power(2,10)
res18: Long = 1024

可能遇到的问题:栈溢出,调用递归函数的次数太多,耗尽了所有已经分配的栈空间。

为了避免栈溢出的情况,使用尾递归。

将乘法移到诶调用函数的最前面,而不要乘以函数调用的结果。

scala> @annotation.tailrec
| def power(x:Int,n:Int,t:Int = 1):Int = {
| if(n < 1) t
| else power(x,n-1,x*t)
| }
power: (x: Int, n: Int, t: Int)Int
scala>
scala> power(3,10)
res19: Int = 59049

6、嵌套函数

函数中定义另外一个内部函数,该内部函数只能在该函数中使用。

scala> def max(a:Int,b:Int,c:Int) = {
| def max1(x:Int,y:Int) = if(x > y) x else y
| max1(a,max1(b,c))
| }
max: (a: Int, b: Int, c: Int)Int
scala> max(2,3,4)
res20: Int = 4

函数优先级:局部嵌套函数优先于外部函数

7、用函数名调用函数

允许不按顺序指定参数

scala> def greet(prefix:String,name:String) = s"$prefix $name"
greet: (prefix: String, name: String)String
scala> val greeting1 = greet("Ms","Brown")
greeting1: String = Ms Brown
scala> val greeting2 = greet(name = "Brown",prefix = "Mr")
greeting2: String = Mr Brown

8、有默认值的参数

可以为任意参数指定默认值,使得调用嗯可以忽略使用这个默认值。

scala> def greet(prefix:String="",name:String) = s"$prefix$name"
greet: (prefix: String, name: String)String
scala> val greeting1 = greet(name = "Paul")
greeting1: String = Paul

从编程风格角度考虑,让必要参数在前面,默认值的参数在后面。

9、多个参数

Scala支持vararg参数,可以定义输参数个数可变的函数,可以用于for的循环迭代器。

要标志一个参数匹配一个或多个输入实参,再函数定义中需要该参数类型后门增加一个星号(*)

scala> def sum(items:Int*):Int = {
| var total = 0
| for (i <- items) total += i
| total
| }
sum: (items: Int*)Int
scala> sum(10,3,434,343)
res25: Int = 790
scala> sum()
res26: Int = 0

10、参数组

用小括号包围参数表,这里提供了另外一个种方式:将参数分解为参数组,每个参数组分别用小括号分隔。

scala> def max(x:Int)(y:Int) = if(x>y) x else y
max: (x: Int)(y: Int)Int
scala> val larger = max(20)(40)
larger: Int = 40

11、类型参数

前面说的都是关于参数”值”参数,即传入函数的输入数据。可以传递类型参数,指示值参数或返回值使用的类型。通过使用类型参数,可以提高函数的灵活性和可重性。好处:参数或返回值的类型不再固定,可以调节。

scala> def identity[A](a:A):A = a
identity: [A](a: A)A
scala> val s:String = identity[String]("Hello")
s: String = Hello
scala> val d:Double = identity[Double](2.71656)
d: Double = 2.71656

12、方法

方法是类中定义的一个函数,Scala中调用方法的标准做法是使用中缀点记法,方法名前面有实例和一个点(.)分隔符作为前缀。

S.length is the length of the string in characters;
S.substring(i) returns the part of the string starting at index i.
S.substring(i,j) returns the part of the string starting at index i and going up to index j-1. You can write S.slice(i,j) instead.
S.contains(T) returns true if T is a substring of S;
S.indexOf(T) returns the index of the first occurrence of the substring T in S (or -1);
S.indexOf(T, i) returns the index of the first occurrence after index i of the substring T in S (or -1);
S.toLowerCase and S.toUpperCase return a copy of the string with all characters converted to lower or upper case;
S.capitalize returns a new string with the first letter only converted to upper case;
S.reverse returns the string backwards;
S.isEmpty is the same as S.length == 0;
S.nonEmpty is the same as S.length != 0;
S.startsWith(T) returns true if S starts with T;
S.endsWith(T) returns true if S ends with T;
S.replace(c1, c2) returns a new string with all characters c1 replaced by c2;
S.replace(T1, T2) returns a new string with all occurrences of the substring T1 replaced by T2;
S.trim returns a copy of the string with white space at both ends removed;
S.format(arguments) returns a string where the percent-placeholders in S have been replaced by the arguments (see example below);
S.split(T) splits the string into pieces and returns an array with the pieces. T is a regular expression (not explained here). To split around white space, use S.split("
s+")

13、编写可读的函数

编写函数的目的就是为了重用,而确保函数可重用性的最好办法就是保证函数对其他开发人员可读。

在scala中,向函数增加Scaladoc首部。案例如下

scala> /**
| * Returns the input string without leading or trailing
| * whitespace,or null if the input string is null
| * @param s the input string to trim,or null
| */
|
| def safeTrim(s:String):String = {
| if(s == null) return null
| s.trim()
| }
safeTrim: (s: String)String
scala> safeTrim("HelloWorld")
res29: String = HelloWorld

发表评论
留言与评论(共有 0 条评论)
   
验证码:

相关文章

推荐文章

'); })();