内建控制结构
scala 内建的控制结构很少,只有 if
while
for
try
match
和函数调用
几种。因为scala 从语法层面支持函数字面量。几乎所有的scala控制结构都会产生值.函数式语言把程序看成是计算值的活动。
if
object InBuildControl {
def main(args: Array[String]): Unit = {
var filename = "default.txt"
if ( ! args.isEmpty)
filename = args(0)
}
} // 指令式风格
object InBuildControl {
def main(args: Array[String]): Unit = {
val filename =
if (! args.isEmpty) args(0)
else "defult.txt"
println(filename)
}
} //函数式风格
println(if (! args.isEmpty) args(0) else "default.txt")
while
object InBuildControl {
def main(args: Array[String]): Unit = {
println(gcdLoop(6,4))
}
def gcdLoop(x: Long,y: Long): Long = { //这就求分子字母最大公约数的一个程序
var a = x
var b = y
while (a != 0){
val temp = a
a = b % a
b = temp
}
b
}
}
var line = ""
do{
line = readLine() //readline()该方法已经过时了
println("read" + line)
}while (line != "")
} //do...while 循环
Unit类型的值是 unit ,写为 ()
给变量赋值操作等式本身返回的也是unit 值
纯指令式风格(递归)实现 求解最大公约数
def gcd(x:Long,y:Long):Long = if (y == 0)x else gcd(y,x%y)
for
for (i <- 1 to 5) println(i) // 12345
for (i <- 1 until 5) println(i) //1234
for (i <- 1 until 5 if i > 2) println(i) //34 if 过滤
/*
i <- 1 to 5
1 to 5 是 Range 类型
i <- 1 to 5 是发生器(generator)(python叫生成器),每一次枚举,名为 i 的新的 val 就被元素值初始化。编译器能够推断出它是Int类型。
*/
for (
i <- 1 to 10
if i > 2
if i % 2 != 0
)print(i) //多个条件过滤 i>2 且 i%2 !=0 才运行此打印命令
val filesHere = (new java.io.File(".")).listFiles
def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines.toList
def grep(pattern: String) = {
for(
file <- filesHere
if file.getName.endsWith(".scala")
line <- fileLines(file)
if line.trim.matches(pattern) //多层嵌套
)println(file + ":" + line.trim)
}
#类似于:
for file in filesHere:
if file.endswith(".scala"):
for line in file.readlines():
if line.strim.matches(pattern):
print (file + ":" + line.trim)
val filesHere = (new java.io.File(".")).listFiles
def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines.toList
def grep(pattern: String) = {
for(
file <- filesHere
if file.getName.endsWith(".scala")
line <- fileLines(file)
//if line.trim.matches(pattern) //多次用到了 line.trim
trimmed = line.trim //流式变量 trimmed 是val 类型的,
if trimmed.matches(pattern)
)//println(file + ":" + line.trim)
println(file + ":" + trimmed)
}
val filesHere = (new java.io.File(".")).listFiles
def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines.toList
def grep(pattern: String) = {
for(
file <- filesHere
if file.getName.endsWith(".scala")
line <- fileLines(file)
if line.trim.matches(pattern) //多层嵌套
) yield line.trim.length // 返回每一行去掉空格之后的长度
} // 最终返回一个数组 Array[Int]
try
使用throw
抛出异常
先创建一个异常对象,然后用throw
抛出
throw new IllegalArgumentException
var aNum = 5
if(aNum % 2 == 0)
print("haha")
else
throw new RuntimeException("anum must be even")// throw 抛出的异常类型为Nothing,因此得到的值为Nothing
var aNum = 5
try{
if(aNum % 2 == 0)
print("haha")
else
throw new RuntimeException("anum must be even")
}catch {
case ex:RuntimeException =>print("aiyou") //捕获 Run...异常,然后调用指定的函数
case ex:IllegalArgumentException => print("hehe") //如果异常不再这两个case之内,那么就会向上传导
}
try...catch...finally
def urlFor(path: String)={
try{
new URL(path)
}catch{
case e: MalformedURLException =>new URL("https://www.baidu.com")
}finally {
print("iiiii")
}
}
def f():Int = try{ return 1} finally {return 2} // 始终返回 2,其实是 2覆盖了 1
def g():Int = try{1} finally {2} //返回1
match
val aArg = "aha"
aArg match{
case "haha" =>println("right") //隐含了break
case "hehe" => println("wrong") // case 后面接的不止是Int,String类型,可以是任何类型的常量或其他东西。
case _ => println("i dont't know") // _ 占位符, 表示默认情况 _ 是常用的用来匹配未知变量的通配符。
}
val aArg = "haha"
val name =
aArg match{
case "haha" => "right" // 返回值
case "hehe" => "wrong"
case _ => "i don't know"
}
println(name)
变量的作用范围
大括号{}
起到引入新的作用范围的作用。大括号能起到遮蔽括号内外同名变量的作用。
因此不同于java的不能创建同名变量,scala可以在大括号内外创建同名变量。
object InBuildControl{
def main(args: Array[String]): Unit = {
val i = 10
for(z <- 1 until 2){
val i = 12
println(i) //12
}
println(i) //10
}
}
子{}
可以访问父{}
的变量
object InBuildControl{
def main(args: Array[String]): Unit = {// 祖 层开始
val i = 10
val a = 23
for(z <- 1 until 2){ //父 层开始
val i = 12 //遮蔽了祖层的同名变量 i
println(i) //12
for (j <- 1 until 2){ //子 层开始
println(i) //12 虽然祖、父层都有i,但是父层遮蔽了祖层的i,所以这里读取的是父层的i
println(a) //23 只有祖 层 才有a 所以没有所谓遮蔽
}//子层结束
}//父层结束
println(i) // 10 打印本层的 i
}//祖层结束
}