Scala002_函数

1 定义函数

在scala中定义函数,需要定义函数的函数名、参数、函数体
scala要求必须给出所有参数的类型,但是不一定给出函数返回值的类型,只要右侧的函数体中不包含递归语句,scala就可以自己根据右侧的表达式推断类出返回类型。

scala> :paste
// Entering paste mode (ctrl-D to finish)

def sayhello(name:String,age:Int) = {
 if(age >= 18){
  printf("Hi,%s,you are a big boy",name)
  println()
  age
 }else{
  printf("Hi,%s,you are a little boy",name)
  println()
  age
 }
}

// Exiting paste mode, now interpreting.

sayhello: (name: String, age: Int)Int

scala> sayhello("Leo",21)
Hi,Leo,you are a big boy
res5: Int = 21

scala>

2 在代码块中定义函数体

单行的函数

scala> def sayhello(name : String) = printf("Hello,%s",name)
sayhello: (name: String)Unit

scala> sayhello("Leo")
Hello,Leo
scala>

如果函数体中有多行代码,则可以使用代码块的方式包裹多行代码,代码块中最后一行的返回值就是整个函数的返回值。

scala> :paste
// Entering paste mode (ctrl-D to finish)

def sum(n:Int) = {
 var result = 0
 for (i <- 1 to n){
  result += i
 }
 result
}

// Exiting paste mode, now interpreting.

sum: (n: Int)Int

scala> sum(4)
res16: Int = 10

scala>

3 递归函数

如果在函数体内递归调用函数自身,则必须手动给出函数的返回类型
例如:实现经典的斐波那契数列:
10
9 + 8
8 + 7+7+6
7+6+6+5+6+5+5+4--------

scala> :paste
// Entering paste mode (ctrl-D to finish)

def fab(n : Int): Int = {
 if(n <= 0) 1
 else fab(n - 1) + fab(n - 2)
}

// Exiting paste mode, now interpreting.

fab: (n: Int)Int

scala> fab(10)
res17: Int = 144

4 默认参数

在scala中,有时我们调用某些函数时,不希望给出参数的具体值,而希望使用参数自身默认的值,此时就定义在定义函数的时使用默认参数。
如果给出的参数不够,则会从左往右依次应用参数。

scala> :paste
// Entering paste mode (ctrl-D to finish)

def sayhello(name:String,age : Int = 20){
 print("Hello, "+name+",your age is "+age)
}

// Exiting paste mode, now interpreting.

sayhello: (name: String, age: Int)Unit

scala> sayhello("Leo")
Hello, Leo,your age is 20
scala> sayhello("Leo",30)
Hello, Leo,your age is 30
scala>

5 带名参数

在调用函数时,也可以按不按照函数定义的参数顺序来传递参数,而是使用带名参数的方式来传递。
还可以混合使用未命名参数和带名参数,但是未命名参数必须排在带名参数前面

scala> sayhello(age=10,name="Leo")
Hello, Leo,your age is 10
#混合使用
scala> :paste
// Entering paste mode (ctrl-D to finish)

def sayhello(firstname : String,middlename : String,lastname: String) = {
 print(firstname + " "+ middlename + " "+ lastname)
}

// Exiting paste mode, now interpreting.

sayhello: (firstname: String, middlename: String, lastname: String)Unit

scala> sayhello("Leo",lastname="Jack",middlename="Tem")
Leo Tem Jack
scala>

6 变长参数

在scala中,有时我们需要将函数定义为参数个数可变的形式,则此时可以使用变长参数定义函数。

scala> :paste
// Entering paste mode (ctrl-D to finish)

def sum(nums : Int*) = {
 var result =  0
 for (num <- nums){
  result += num
 }
 result
}

// Exiting paste mode, now interpreting.

sum: (nums: Int*)Int

scala> sum(1,2,3)
res32: Int = 6

scala>

7 使用序列调用变长参数

在如果想要讲一个已有的序列直接调用变长参数函数,是不对的。如下

scala> 1 to 5
res33: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)

scala> 1.to(5)
res34: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)

scala> sum(1 to 5)
<console>:13: error: type mismatch;
 found   : scala.collection.immutable.Range.Inclusive
 required: Int
       sum(1 to 5)
             ^

scala>

此时需要使用scala特殊的语法将参数定义为序列,让scala解释器能够识别。这种语法非常有用!一定要好好注意,在spark的源码中大量使用到了。

scala> sum(1 to 3:_*)
res36: Int = 6

案例:使用递归函数实现累加

scala> def sum2(nums:Int*):Int={
     | if(nums.length == 0) 0
     | else nums.head + sum2(nums.tail:_*)
     | }
sum2: (nums: Int*)Int

scala> sum2(1,2,3,4)
res38: Int = 10

8 过程

在scala中,定义函数时,如果函数体直接包裹在了花括号里面,而没有使用=连接,则函数的返回值类型就是Until。这样的函数被称之为过程。过程通常用于不需要返回值的函数。
过程还有一种写法,就是函数的返回值类型定义为Until

#这是不是过程
scala> def sayhello(name : String) = "Hello," + name
sayhello: (name: String)String
#这个是过程
scala> def sayhello(name:String){print("Hello,"+name)}
sayhello: (name: String)Unit

scala> sayhello("Leo")
Hello,Leo
scala> def sayhello(name : String) = "Hello," + name
sayhello: (name: String)String

scala> sayhello("Leo")
res40: String = Hello,Leo
#这个是过程
scala> def sayhello(name : String):Unit = "Hello," + name
sayhello: (name: String)Unit

scala> sayhello("Leo")

9 lazy值

在scala中,提供了lazy值的特性,也就是说,如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会发生计算。这种特性对于耗时的计算操作特别有用,比如打开文件进行IO,进行网络IO等。

scala> import scala.io.Source._
import scala.io.Source._

scala> lazy val lines = fromFile("C://Users//zhu//Desktop//test.txt").mkString
lines: String = <lazy>

scala> print(lines)
Hello world
scala> lazy val lines = fromFile("C://Users//zhu//Desktop//test1.txt").mkString
lines: String = <lazy>

scala> print(lines)
java.io.FileNotFoundException: C:\Users\zhu\Desktop\test1.txt (系统找不到指定的文件。)
  at java.io.FileInputStream.open0(Native Method)
  at java.io.FileInputStream.open(FileInputStream.java:195)
  at java.io.FileInputStream.<init>(FileInputStream.java:138)
  at scala.io.Source$.fromFile(Source.scala:91)
  at scala.io.Source$.fromFile(Source.scala:76)
  at scala.io.Source$.fromFile(Source.scala:54)
  at .lines$lzycompute(<console>:14)
  at .lines(<console>:14)
  ... 32 elided

scala> val lines = fromFile("C://Users//zhu//Desktop//test1.txt").mkString
java.io.FileNotFoundException: C:\Users\zhu\Desktop\test1.txt (系统找不到指定的文件。)
  at java.io.FileInputStream.open0(Native Method)
  at java.io.FileInputStream.open(FileInputStream.java:195)
  at java.io.FileInputStream.<init>(FileInputStream.java:138)
  at scala.io.Source$.fromFile(Source.scala:91)
  at scala.io.Source$.fromFile(Source.scala:76)
  at scala.io.Source$.fromFile(Source.scala:54)
  ... 32 elided

scala> def getlines = fromFile("C://Users//zhu//Desktop//test1.txt").mkString
getlines: String

scala> getlines
java.io.FileNotFoundException: C:\Users\zhu\Desktop\test1.txt (系统找不到指定的文件。)
  at java.io.FileInputStream.open0(Native Method)
  at java.io.FileInputStream.open(FileInputStream.java:195)
  at java.io.FileInputStream.<init>(FileInputStream.java:138)
  at scala.io.Source$.fromFile(Source.scala:91)
  at scala.io.Source$.fromFile(Source.scala:76)
  at scala.io.Source$.fromFile(Source.scala:54)
  at .getlines(<console>:14)
  ... 32 elided

scala>

10 异常

在scala中,异常处理和捕获机制与java中是很类似的

# 1
scala> :paste
// Entering paste mode (ctrl-D to finish)

try{
 throw new IllegalArgumentException("Illegal argument!!!")
}catch{
 case _: IllegalArgumentException => print("sorry,error!!!")
}finally{
 print("release io resource!!!")
}

// Exiting paste mode, now interpreting.

sorry,error!!!release io resource!!!

# 2 没有catch成功
scala> import java.io._
import java.io._

scala> :paste
// Entering paste mode (ctrl-D to finish)

try{
 throw new IOException("io exception!!!")
}catch{
 case _: IllegalArgumentException => print("illegal argement!!!")
}

// Exiting paste mode, now interpreting.

java.io.IOException: io exception!!!
  at .liftedTree1$1(<console>:16)
  ... 37 elided

# 3 catch成功
scala> :paste
// Entering paste mode (ctrl-D to finish)

try{
 throw new IOException("user defined exception")
}catch{
 case e1:IllegalArgumentException => println("illegal argument!!")
 case e2:IOException => println("io exception")
}

// Exiting paste mode, now interpreting.

io exception

scala>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值