鲁春利的工作笔记,好记性不如烂笔头



Scala只内置了为数不多的几种程序控制语句:if , while, for, try, match等。

1、判断(if)

格式:

if (A) B; else C

if (!A) C

package com.lucl.scala

/**
 * @author luchunli
 */
object IfControlStructure {
  
  // 返回类型是可选的,默认最后一行的值为返回值,Scala可以根据返回值推导出返回类型
  def getMax (a : Int, b : Int) = if (a > b) a else b;
  
  // 未指定else实际上为:else Unit,简写为()
  def getMin (a : Int, b : Int) = if (a > b) b;
  
  def main (args : Array[String]) {
    println(getMax(3, 5));    // 5
    println(getMin(5, 3));    // 3
    println(getMin(3, 5));    // ()
  }
}


2、循环(while/do)

package com.lucl.scala

/**
 * @author luchunli
 */
object WhileControlStructure {
  
  def whileFunc () {
    var n = 10;      // 如果n = 0, 不会有任何输出
    while (n > 0) {
      print (n + ", ");
      n -= 1;
    }
    println;
  }
  
  def doWhileFunc () {
    var m = 10;      // 如果m = 0,会输出一次0
    do {
      print(m + ", ");
      m -= 1;
    } while (m > 0);
  }
  
  def main (args : Array[String]) {
    whileFunc();
    doWhileFunc;
    
      
    var line = "";
    while (line == "bye") {
      // line = readLine 被标记为@deprecated,采用如下方式实现
      line = StdIn.readLine;
      // ......
    }
  }
}

    说明:       

    对于while循环如果是(line = readLine()) != "bye"的话是无法退出while循环的,因为赋值语句的返回结果(即line = readLine()作为一个整体处理后的结果是Unit,然后再和bye进行比对)和字符串是不相等的。

    比如:

var y = 2;
varl x = y = 1;        // 此时y=1, x=Unit(打印出来为())


3、枚举(for)

     Scala中没有Java中的for(;;)形式的循环,其格式为:

    for (i <- e) { E(i) }

    for (i <- e1; j <- e2; if ...) { E(i) }

    for (i <- e) yield E(i)        // 生成集合

    其中 <– f的语法结构,在Scala中称为“生成器 (generator)”。

    For表达式能用任意条件进行各种形式枚举,而在枚举的过程中能实现绝大部分的循环功能而不必使用变量。

    遍历e中的元素,每次获取名为i的新值;对于每一次枚举,函数体E(i)都会被执行一次,而i在枚举时赋值。

    e可以是各种集合,包括数组、列、表达式等,或是有上下界的数值范围。

package com.lucl.scala

import java.io.File
import scala.io.StdIn

/**
 * @author luchunli
 */
object ForControlStructure {
  def main (args : Array[String]) {
    // 代码块
    {
      for (i <- 1 to 5) print(i + ", ");      // 1, 2, 3, 4, 5,
      println;
      // 指定步长
      for (i <- 1 to (5, 2)) print(i + ", "); // 1, 3, 5, 
      println;
      for (i <- 1 until 5) print(i + ", ");   // 1, 2, 3, 4, 
      println;
      for (i <- 1 to 3; j <- 1 to 3; if i < j) print (i + "-" + j + ", ");
      println;
      for (i <- "hello")  print(i + ", ");  // h, e, l, l, o, 
      println;
    }
    // 代码块
    {
      var array = Array("hello", "world", "!");
      for (arr <- array) print(arr + " ");    // hello world ! 
      println;
      
    }
    // 代码块
    {
      val files = (new File("D:\\LuclAppServ\\luchunli")).listFiles;
      for (file <- files; if file.isFile() && file.getName.endsWith(".gz")) println(file)
    }
    // 代码块
    {
      // 生成新的集合
      val res = for (i <- 1 to 5) yield 2 * i;
      println(res);    // Vector(2, 4, 6, 8, 10)
      var str = for (i <- "hello".reverse) yield i;
      println(str);    // olleh
    }
  }
}

 

4、break和continue

    Scala的内置的控制结构时,没有提到使用break和continue,Scala提供了多种方法来替代break和continue的作用。一个简单的方法是使用一个if语句来代替一个continue,使用一个布尔控制量来去除一个break。

    下面的Java代码使用continue和break在循环结构中:

int i = 0;
boolean fonudIt = false;
while ( i < args.length) {
    if (args[i].startsWith("-")) {
        i += 1;
        continue;
    }
    if(args[i].endsWith(".scala")) {
        foundIt = true;
        break;
    }
    i += 1;
}

    使用if和boolean变量,逐句将这段实现使用Scala来实现(不使用break和continue)如下:

var i = 0;
var foundIt = false;
while (i < args.length && 
!foundId) {
    if (!args(i).startsWith("-") && 
args(i).endsWith(".scala")) {
        foundIt = true;
    }
    i += 
1;
}

    可以看到,使用if (于前面continue条件相反)去掉了continue,而重用了foundIt布尔变量去掉了break。

    

5、匹配(match)

    Scala的Match表达式支持从多个选择中选取其一,类似其它语言中的switch语句。

    通常来说,Scala的match表达式支持任意的匹配模式。

a match {
    case e1 => E1        // 匹配元素e1
    case e2 => E2        // 匹配元素e2
    case _  => Eo        // 其他情况
}

# 给定类型
a match {
    case e1 : String : E1
    case e2 : Int : E2
    case _ : E3
}

    和Java的switch相比有几点不同:
    一、Java的case仅限于int或是枚举类型,Scala任何类型的常量都可以用在case语句中;
    二、Java中每个case都必须有break,Scala每个case语句均无需使用break;
    三、Java中缺省匹配为default,Scala的缺省匹配为”_”。

package com.lucl.scala

/**
 * @author lucl
 */
object CaseControlStructure {
  
  def caseMethod1 (name : String) {
    name match {
      case "human" => println("human");
      case "animal" => println("hahaha");
      case _ => println("unknown");
    }
  }
  
  def caseMethod2 (array : Array[Any]) {
    for (arg <- array) {
      arg match {
        case str : String => println("The string with value " + str + ".");
        case i : Int => println("The integer with value " + i + ".");
        case _ => println("Unknown type.");
      }
    }
  }
  
  def caseMethod3 (value : String) : String = {
    value match {
      case "a" => "All";
      case "o" => "Oters";
      case _ => "unknown";
    }
  }
  
  def main(args: Array[String]): Unit = {
    // 接收固定参数并判断
    caseMethod1("human");
    // 接收数组并判断参数类型
    var array = Array("hello", 1, 'c');
    caseMethod2(array);
    // 带有返回值
    var checkType = caseMethod3("a");
    println(checkType);
  }
}


6、异常处理(throw/try)

    Scala的异常处理和其它语言比如Java类似。

def half (n:Int) : Int = {
   if (n % 2 == 0) {
        n / 2;
    } else {
        throw new RuntimeException("n must be even");
    }
}

    try-catch表达式的基本用法和Java一样,如果try块中代码在执行过程中出现异常,将逐个检测每个catch块。

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
try {
    val f  = new FileReader("input.txt");
} catch {
    case ex : FileNotFoundException ==> // handle missing file
    case ex : IOException => // handle other I/O error
}

    Scala也支持finally语句,不管try块是否抛出异常,都会执行。    

try {函数体} catch {case ...; case ...} finally {A.close();}
// 通过异常赋值
def f():Int = try{1} finally {2}
// 或
def urlFor(path:String) =
try {
    new URL(path)
} catch {
    case e: MalformedURLException => new URL("http://www.scala-lang.org")
}