二、Scala控制结构和函数

1.条件表达式

Scala中的if/else表达式:val s = if (x>0) 1 else -1,这个表达式等价于:if(x>0) s = 1 else s = -1
在Scala中,每一个表达式都有一个类型。
if (x>0) 1 else -1的类型是Int
②混合表达式的类型为两个分支类型的公共超类型,例如:if (x>0) "positive" else 1,其类型为Intjava.lang.String的公共超类型Any
③如果else部份缺失,则其将被Unit类代替,例:if (x>0) 1等价于if (x>o) 1 else (),可以把()理解为表示”无有用值“的占位符。

2.语句终止

①同一行写多个语句时用;隔开
②在写较长的语句时,需要分成两行,确保第一行以一个不能用作语句结尾的符号结尾,例如在一个求和语句中,在第一行以+结尾。

3.块表达式和赋值

①当你需要在逻辑分支或者魂环中放置多个动作时,可以使用块语句{语句序列},块中最后一个表达式的值就是块的值,这种特性对于对某个val的初始化需要分多步完成的情况很有用。

val distance = {
    
    val dx = x-x0; val dy = y - y0; sqrt(dx * dx + dy * dy)}

此块的值就是最后开方的结果

②在Scala中,赋值动作本身是没有值的,它的值时Unit类型的,一个以赋值语句结束的块的值时Unit类型的。例:{ r = r*n; n-=1}的值类型就是Unit
因此,你不能将赋值语句串在一起,例:x = y = 1,将y = 1的值Unit赋给x似乎没有意义。

4.输入和输出

①输出
字符串插值:
print (f"Hello, $name! In six months, you'll be ${age + 0.5}%7.2f years old.%n")
其中:被格式化的字符串以字母f打头,以$打头的表达式可以用相应的变量替换。用f插值器比用printf方法更好,因为它是类型安全的。字符串插值器有三种,不详细展开。
②输入
你可以使用scala.io.StdInreadLine方法冲控制台读取一行输入。如果是想读取数字,Boolean或者是字符,则使用readInt,readDouble,readBytes,readShort,readLong,readFloat,readBoolean,readChar。其中,readLine不同的是,它带一个参数作为提示字符串StdIn.readLine("your name:")

5.循环

while使用方法与其他语言没啥区别
for区别大了:for (i <- 表达式)

for(i<- 1 to 10)
	r=r*i

var sum = 0
for(ch<-"hello")
	sum+=ch

③Scala中没有提供break和continue语句来退出循环,可以采用如下方法:

  • 使用Boolean型的控制变量
  • 使用嵌套函数–可以在函数当中return
  • 使用Breaks对象中的break方法
import scala.util.control.Breaks._
breakable{
    
    
	for(`````){
    
    
		if(````)break;//退出breakable块
		····
	}
}
但不建议使用这种机制,比较慢

6.高级for循环

可以以 变量<-表达式的形式提供多个生成器,用分号将他们隔开

for(i<-1 to 3; j<-1 to 3)
	·····
相当于双重循环,i为外循环,j为内循环

每个生成器都可以带上守卫(此处要注意if前面是没有分号的)

for(i<-1 to 3; j<-1 to 3 if i!=j)
过滤掉i==j的情况

还可以使用定义

for(i<-1 to 3;from 4-i; j<-from to 3)

注意:
如果for循环的循环体以yield开始,则该循环会构造出一个集合,每一次迭代生成集合中的一个值:

for(i<-1 to 10) yield i%3
将交出一个vector(120120·····)

可以用换行符代替分号

7.函数

def abs(x:Double) = if(x>=0) x else -x

如上例所示:你需要给出函数的名称、参数和函数体,必须给出所有参数的类型
只要函数不是递归的,就可以不指定返回值类型。Scala编译器可以通过=右侧的表达式推断返回值类型。但是对于递归函数,必须指出返回值类型:

def fac(n:Int) :Int = if(n<=0) 1 else n*fac(n-1)

8.默认参数和带名参数

默认值和其他语言区别不大
可以在提供参数的时候指定参数名

decorate(left = "<<<",str = "Hello",right = ">>>")

因为指定了参数名,所以参数的顺序可以和参数列表中的不一致

9.变长参数

实现一个可以接受可变长度参数列表的函数

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

该函数的参数是任意个

val s = sum(1,4,5,6,6,6,6)

函数得到的是一个类型为Seq的参数

如果你已经有一个值序列了,不能将该值序列直接传入该函数。如果sum函数被调用时传入的参数是单个参数,则该参数必须是单个整数,而不是一个整数区间:val s = sum( 1 to 5) //是错误的,正确的写法是val s = sum(1 to 5:_*),其中_*用来将它转换为参数序列。

**注意:**当你调用变长参数且参数类型为Object的Java方法时,比如Print Stream,Printf,MessageFormat.format,需要手工对基本类型进行转换。

val str = MessageFormat.format("The answer to {0} is {1}",
"everything",42.asInstanceOf[AnyRef])

10.过程

对于没有返回值的函数有特殊的表示方法,如果函数体用{}包着,但是前面没有=,则说明返回值类型时Unit,该函数叫做过程。

def box(s :String){
    
    
····
}

11.懒值

val被声明为lazy时,它的初始化将被推迟,直到我们首次对它取值。

lazy介于val和def之间,val是被定义时就取值,而def是每次调用时取值
lazy val words = scala.io.Source.fromFile("").mkString

12.异常

Scala没有“受检”异常,不需要我们声明函数或者方法可能会抛出某种异常。不太了解,暂不详细写。

猜你喜欢

转载自blog.csdn.net/Cxf2018/article/details/109406540