zoukankan      html  css  js  c++  java
  • 3.Scala-控制结构和函数

    第3章 控制结构和函数

    Java 中把表达式和语句当成两个不同的东西,表达式有值,语句没有值,
    只是控制结构。在 Scala 中,几乎所有语法结构都有值。

    3.1 If else 表达式

    scala> val x = 5
    x: Int = 5
    
    scala> val s = if( x > 0 ) 1 else -1
    s: Int = 1
    S 为什么会有值?
    If 语句的返回类型取决于最后一条语句。语句后面的分号不是必须的。
    Scala 没有三元运算符,不需要。
     
     
      If 表达式会有一个返回值类型,如果 if 或者 else 返回的类型不一样,就
    返回 Any 类型(所有类型的公共超类型)。 
    scala> val s1 = if( x > 0) "hello" else -1
    s1: Any = hello
    
    scala> val s3 = if ( x < 0 ) "hello"
    s3: Any = ()
     
      如果缺少一个判断,什么都没有返回,但是 Scala 认为任何表达式都会
    有值,对于空值,使用 Unit 类,写做()【叫做无有用占位符,相当于 java
    中的 void】 
    scala> val s4 = if(x < 0 ) "hello" else ()
    s4: Any = ()
    注:行尾的位置不需要分号,只要能够从上下文判断出语句的终止即可。但是如果
    在单行中写多个语句,则需要分号分割。在 Scala 中,{}快包含一系列表达
    式,其结果也是一个表达式。块中最后一个表达式的值就是块的值。 

    3.2 while 表达式

      Scala 提供和 Java 一样的 while 和 do 循环,与 If 语句不同,While 语句
    本身没有值,即整个 While 语句的结果是 Unit 类型的()。 
    while (n > 0) { 
        r = r * n
        n -= 1
        println(r)
    }
    do{
        r = r * n
        n -= 1
        println(r)
    }while(n > 0)
    注:scala 并没有提供 break 和 continue 语句来退出循环,如果需要 break,可以
    通过几种方法来做 1、使用 Boolean 型的控制变量 2、使用嵌套函数,从函数中
    return 3、使用 Breaks 对象的 break 方法。 
    //循环的终止
    import scala.util.control.Breaks
    val looper = new Breaks() //括号可以省略
    
    var count = 0
    looper.breakable{         // . 可以替换成空格
      while(count <= 100){
        count += 1
        println(count)
        if(count == 10){
          looper.break()
        }
      }
    //多重while循环的终止
    val whileLooper1 = new Breaks
    val whileLooper2 = new Breaks
    
    whileLooper1.breakable{
      while (true){
        count += 1
        if(count == 10){
          whileLooper1.break()
        }
        
        whileLooper2.breakable{
          while (true){
            if(count == 20){
              whileLooper2.break()
            }
          }
        }
        
      }
    }

    3.3 for 表达式 

      Scala 也为 for 循环这一常见的控制结构提供了非常多的特性,这些 for
    循环的特性被称为 for 推导式(for comprehension)或 for 表达式(for
    expression)。
     
     
      推导式一词起源于函数式编程。 
    像 变量名 <- 集合 这样的表达式也被称为生成器表达式,该表达式会
    基于集合生成单独的数值。 
    //多重for循环
    for(i <- 1 to 3; j <-1 to 3){
      println(i + "----" + j)
      println()
    }
    //输出10 9 8 7 ... 1
    for(i <- Range(10, 0, -1)){
      println(i)
    }
    
    
    //输出1~9
    for(i <- 1 until 10){
      println(i)
    }
      保护式,也叫守卫,可以添加一个或者多个守卫,不需要 continue 语句

     

    //实现1~10的输出,只输出偶数
    for (i <- 1 to 10 if i % 2 == 0){
      println(i)
    }

      For 推导式可以引入变量 

    //在for循环中添加变量表达式
    for(i <- 1 to 10; j = 10 - i; m = j * i){
      println("j:" + j)
      println("m:" + m)
    }
      需要返回值怎么办?
      使用 yield 关键字便能在 for 表达式中生成新的集合。for-yield 表达式所
    生成的集合类型将根据被遍历的集合类型推导而出。 

     

    scala> val forResult = for (i <- 1 to 10) yield i
    forResult: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
     尖叫提示:{}和()对于 for 表达式来说都可以。for 推导式有一个不成文的约定:当
    for 推导式仅包含单一表达式时使用原括号,当其包含多个表达式时使用大括
    号。值得注意的是,使用原括号时,早前版本的 Scala 要求表达式之间必须
    使用分号。

     

    //使用花括号作为for循环的条件包裹
    for{
      i <- 1 to 3
      m = i * 2
    }
      println(m) //需要使用具体的逻辑

    Scala 随堂笔记

    一、变量的声明
        ** val:初始化后不能被再次赋值
        ** var:初始化之后可以多次复制
        ** if else:有返回值,如果多个逻辑控制代码块,返回不同的值,则返回为:Any
        ** 循环:
            ** while
                -- 返回值类型为Unit -> ()
                -- break的用法
            ** for
                -- 基本形式
                -- 守卫
                -- 表达式
                -- 多个循环体放在同一个参数体内
                -- 输出遍历元素到一个集合中并返回:yeild i
                -- {}花括号形式,用的不多

    3.4 函数

      Scala 提供了很多函数,如果 math 函数,Java 中通常通过静态方法来模
    拟。函数定义如下:
     
      def 函数名(参数名:类型…)[: 返回类型] = 函数体
    比如:
        def play(a1 : Int, a2 : Int) : String = {
          (a1 + "," + a2) }
        def play(a1 : Int, a2 : Int)
    = { //返回值可以省略
          a1 + a2 }

        def paly(a1 : Int, a2 : Int) = a1 + a2

        def paly = 1;
     
      //标准形式
        def play1(a1: Int, a2: Int): String = {
          String.valueOf(a1 + a2)
        }
        println(play1(10, 20))
    
        //省略返回值形式(返回的是循环中最后一行的值)
        def play2(a1: Int, a2: Int) = {
          a1 + a2
        }
        println(play2(10, 10))
    
    
        //省略花括号形式
        def play3(a1: Int, a2: Int) = a1 + a2
        println(play3(5, 5))
    
    
        //返回Unit类型的函数
        def play4(a1: String) : Unit = {
          println(a1)
        }
    
    
        //返回Unit类型的函数,但是没有显示指定返回类型。(当然也可以返回非Unit类型的值)
        def play5(a1: String) = {
          println(a1)
        }
    
    
        //返回类型有多种可能,此时也可省略Unit
        def play6(a1: String) = {
          if(a1.length >= 3)
            a1 + "hello"
          else
            3
        }
    
    
        //可选参数
        def play7(a1: Int, a2: Int = 10) = {
          a1 + a2
        }
        println(play7(1))
    
    
        //变长参数
        def play8(args: Int*) = {
          for(i <- args){
            println(i)
          }
        }
        play8(1,2,3,4,5)
    
    
        //递归函数:在使用的时候必须要有明确的返回值类型
        //递归实现阶乘
        def factorial(n : Int) : Int = {
    
          if(n == 1)
            n
          else
            factorial(n - 1) * n
    
        }
        println(factorial(3))
     
    注:1、Scala 可以通过=右边的表达式 推断出函数的返回类型。如果函数体需要
    多个表达式,可以用代码块{}。
    2、可以把 return 当做 函数版本的 break 语句。
    3、递归函数一定要指定返回类型。
    4、变长参数通过* 来指定,所有参数会转化为一个 seq 序列
    5、_* 告诉编译器 Range 当做参数序列化处理。
    6、Head 是获得首元素,tail 是获取剩下元素的序列。

    3.5 过程

    我们将不返回值得函数叫做过程,返回类型是 Unit,他是没有=号的。

    1)定义过程示例1:(显示的返回值类型为Unit)

    def shout1(content: String) : Unit = {
      println(content)  
    }

    2)定义过程示例2:(隐式的返回值类型是Unit)

    def shout1(content: String) = {
      println(content)  
    }

    3)定义过程示例3:(没有 = 号)

    def shout1(content: String) {
      println(content)  
    }

     

    3.6 匿名函数

        //匿名函数
        /*
          * 1、匿名函数右边的函数体应该使用 => 符号来指定
          * 2、匿名函数的函数体,可以是一个包含多行代码的代码块
          * 3、函数的类型,为参数个数的类型
         */
        val play10 = () => 0
        println(play10) //<function0> 表示传参个数为0
        println(play10()) //0
    
        val play11 = (a1 : Int) => 0
        println(play11) //<function1> 表示传参个数为1
    
        val play12 = (a1 : Int, a2 : Int) => {
          a1 + a2
          a2 - 10 + a1
        }
        println(play12) //<function2>
        println(play12(10, 20)) //20

    3.7 懒值

    当 val 被声明为 lazy 时,他的初始化将被推迟,直到我们首次对此取
    值。
    懒值使用注意:
    1) 用于初始化开销比较大的语句。
    2) 可以解决循环依赖问题。
    3) 是开发懒数据结构的基础。 

    1)lazy 示例:通过 lazy 关键字的使用与否,来观察执行过程

        def play1(a1: Int) = {
          println("play1方法被执行," + "a1:" + a1)
          a1
        }
    
        lazy val l1 = play1(10)
        val l2 = play1(20)
        println("l1变量定义完毕")
        println(l1)
    
        /*
        结果:
        play1方法被执行,a1:20
        lazy变量定义完毕
        play1方法被执行,a1:10
        10
         */

    3.8 异常

      当碰到异常情况时,方法抛出一个异常,终止方法本身的执行,异常传
    递到其调用者,调用者可以处理该异常,也可以升级到它的调用者。运行系
    统会一直这样升级异常,直到有调用者能处理它。 如果一直没有处理,则终
    止整个程序。
     
      Scala 的异常的工作机制和 Java 一样,但是 Scala 没有“受检”异常,你
    不需要声明说函数或者方法可能会抛出某种异常。受检异常在编译器被检
    查,java 必须声明方法所会抛出的异常类型。
     
      抛出异常:用 throw 关键字,抛出一个异常对象。所有异常都是
    Throwable 的子类型。throw 表达式是有类型的,就是 Nothing,因为 Nothing
    是所有类型的子类型,所以 throw 表达式可以用在需要类型的地方。 
    //并不像 Java 代码那样,需要声明方法会抛出异常,这给程序员省去理论很多烦恼。
    def divide(x: Int, y: Int): Int = {
        if (y == 0) throw new Exception("Divide by zero")
        else x / y
    }
      捕捉异常:
      在 Scala 里,借用了模式匹配的思想来做异常的匹配,因此,在 catch 的
    代码里,是一系列 case 字句。
      异常捕捉的机制与其他语言中一样,如果有异常发生,catch 字句是按次
    序捕捉的。因此,在 catch 字句中,越具体的异常越要靠前,越普遍的异常越
    靠后。 如果抛出的异常不在 catch 字句中,该异常则无法处理,会被升级到
    调用者处。
      异常捕获通常采用模式匹配的语法: 
    try { 
     process(in)
    } catch { 
     case ex: IOException => println(ex)
    } finally { 
     in.close()}
      finally 字句用于执行不管是正常处理还是有异常发生时都需要执行的步
    骤,一般用于对象的清理工作。 
    注:1、Throw 的类型为 Nothing,存在 exception 的 if 语句类型返回类型。
    object ExceptionSyllabus {
    
      def divider(x: Int, y: Int): Float = {
    
        if(y == 0) throw new Exception("0 不能作为除数")
        else x/y
    
      }
    
      def main(args: Array[String]): Unit = {
    
        try {
          println(divider(10, 0))
        } catch {
          case ex:Exception => println("成功捕获异常" + ex.getMessage)
    //      case ex:Throwable => println("成功捕获异常" + ex.getMessage)
        } finally {}
    
      }
    
    }
  • 相关阅读:
    智能实验室-杀马(Defendio) 4.12.0.800
    智能实验室-结构化存储浏览器(SSExplorer) 1.7.0.170
    智能实验室-全能优化(Guardio) 4.94.0.830
    智能实验室-全能优化(Guardio) 4.9.0.790
    IT餐馆—第二十二回 控件
    当DiscuzNT遇上了Loadrunner(中)
    在Discuz!NT中进行缓存分层(本地缓存+memcached)
    介绍三个Silverlight 在线编辑器控件
    玩玩负载均衡在window与linux下配置nginx
    IT餐馆—第十八回 祭奠
  • 原文地址:https://www.cnblogs.com/LXL616/p/11105476.html
Copyright © 2011-2022 走看看