• Scala具体解释---------控制结构和函数


    条件表达式:

               Scala的if else语法结构和Java的一样。只是,Scala的if else表达式有值。这个值就是跟在if或者else后面的表达式的值。

             比如: if(x>0) 0 else 1 

             该表达式的值就是0或者1,详细的依据x值推断。


              能够将if else表达式的值赋值给变量:

               val s=if(x>0) 0 else 1

               这个跟例如以下语句一致:

              if(x>) s=0 else s=1

              当然。第一种写法更好,它能够用来初始化一个val(常量),而另外一种s必须是var(变量)。


            注:Scala中的分号(;)绝大多数情况下没必要的。


            Java中的 x>0 ? 0:1 等同于 Scala表达式if(x>0) 0 else 1


            Scala中,每一个表达式都有一个类型。

    表达式if(x>0) 0 else 1的类型是Int,由于两个分支的类型都是Int。


             混合类型表达式if(x>0) "hello" else 1。这个表达式的类型是两个分支类型的公共超类型,演示样例中,“hello”是java.lang.String类型,1是Int类型,

            其公共超类型为Any。


            假设else部分没有,if(x>0) 0 ,有可能if没有输出值。但在Scala中,每一个表达式都是有值的。该演示样例中,假设if没有输出值。那么其输出就是一个“无实用值”占位符,

    写作(),其类是Unit类。类似Java中的Void。上述语句等同于if(x>0) 0  else () 。


         注: 在Scala中没有Switch语句,其存在强大的模式匹配机制(后面会讲到)。


           语句终止:

                在Java中,每一个语句都有分号,而在Scala中,行尾的位置不须要分号。在}、else及类似的位置也不必写分号。仅仅须要可以从上下文推断这里是语句终止就可以。

                假设须要在单行写下多个语句。就须要分号将这些语句隔开。

    如:

                if(x>0) { k = r*x ; n +=4}  通过分号将k = r*x  与n +=4 这个语句隔开。因为存在} 。全部n +=4结尾不须要加分号。

                假设书写过长的语句。须要分开两行来写的话,确保第一行以一个不能用做语句结尾的符号结尾。比較好的选择是用操作法结尾。

               如:  sum = s0 + (V1-V2)*t +   //  告诉解析器这里不是语句的结尾

                         0.8*(V3-V4)*t+s1

                  在实际编码中,通过使用Kemighan&Ritchie风格的花括号编码。如:

                  if(x>0) {

    n = n*x

                            x -=1

                     }            

          以{结尾告诉编译器后面还存在内容。


           块表达式和赋值:

                  Java中。块语句是一个包括于{}中的语句序列。

    但逻辑分支或者循环中放置多个语句是,都能够使用块语句。

                  Scala中,{}块语句包括一系列的表达式,其结果也是一个表达式。

    块的最后一个表达式的值就是块的值。

          这个特性对某个val初始化须要分多个步骤完毕的情况非常实用。

    如:

                  val dis = { val x = t1-t2; val y = t3 -t4 ; sum(x,y)}

                  {}块中取值最后一个表达式,即sum(x,y)。

    变量x,y对程序的其他部分不可见。

                  Scala中赋值动作本身没有值。更准确的说。他们的值是Unit类型的,类似Java中的void。写作();

                   一个以赋值语句结尾的块。如:{r -=2;n= r+1} 的值是Unit类型的。

                   语句: x = y =1 //别这么做

                   y=1的值是(),故x的值是(),相信你的本意不是这样。


         输入和输出:

              假设须要打印。用print或者println函数,后者打印完毕后会追加一个换行符。

              print ("hello")

              println("world")

            等价于 println("hello"+"world"),这个类似Java中的System.out.println("hello"+"world");

           

        循环:

      Scala拥有与Java一样的while和do循环。如:

                 while(n>0) {

    r = r*n

                    n -=1

                 }

             scala没有同java中for(初始化变量;检查变量是否满足条件;更新变量 )相应的循环结构。在Scala中你有两个选择:

                 1:使用while循环。

                  2:使用例如以下for语句;

                           for(i <- 1 to n)

                                      r = r *i

                     这个是RichInt类的to方法, 1 to n 这个调用返回数字1到数字n的区间。

                     for(i <- 表达式)让变量i遍历<-右边的表达式中的全部值。遍历怎样运行,取决于表达式的类型。

                    在for循环的变量之前并没有声明变量为val或者var,该变量的类型是集合的元素类型。循环变量的作用域一直持续到循环结束。


                   遍历字符串或者数组时。通常使用0到n-1的区间。在Scala中能够用util方法而不是to方法。

    util方法返回一个并不包括上限的区间。

                   val s = "hello"

                   var sum = 0

                   for(i <- 0 to util s.length) 

                       sum += s(i)

                   这里i的最后一个取值为s.length-1


                注:Scala中没有提供break和continue语句退出循环。


       Scala退出循环的方式:

                         1.使用Boolean类型的控制变量

                          2.使用嵌套函数--能够从函数中return

                           3.使用Breaks对象的break方法:

                            


        高级for循环和for推导式:    


                            1:使用变量<-表达式形式提供多个生成器。分号切割

                                   

            


    2:每一个生成器能够带一个守卫,以if开头的Boolean表达式:(if之前没有分号)

                    

                     3:能够使用随意多的定义,引入能够在循环中使用的变量:

    分析:i == 1 时,from=3; j从3 到3 故输出13

                                                i==2 时,from=2;j从2到3。循环两次,故输出22,23

                                               i== 3 时。from=1;j从1到3,循环3此,故输出31 32 33


                     4:for循环的循环体内已yield開始,则给循环会构造出一个集合,每次迭代生成集合中的一个值。这类循环称为推导式。

                            

                 其类型是Vector。


                for推导式生成器的集合与它的第一个生成器的类型是兼容的。

               

                         

            第一个for循环 。第一个类型是 String ;

            第二个for循环。第一个类型是Int;


    Scala基础之函数:


        Scala除了方法,还支持函数。方法对对象进行操作,函数不是。

         定义函数,须要给出函数的名称、參数和函数体。如:

          def sum(x:int) = if(x>=0) x else -x

          函数须要给出全部參数的类型。仅仅要函数不递归。就不须要知道返回列下。Scala能够依据=号右側表达式推导出放回类型。


          假设函数体须要多个表达式完毕。能够使用代码块。

    块的最后一个表达式的值就是函数的返回值。如:

            

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. def sum(n:Int) = {  
    2.   
    3.       for (i <- 1 to 10)   
    4.             r = r*i  
    5.             r  
    6.  }   

             此函数r即是函数的返回值。

    假设使用return返回r的值,那么须要明白指定函数返回类型,例如以下所看到的:

             

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. def sum(n:Int):Int = {  
    2.   
    3.       for (i <- 1 to 10)   
    4.             r = r*i  
    5.            return r  
    6.  }    

              其与上面的是一样的。仅仅是上面的写法更简洁。


         假设是递归函数,相同须要指定返回类型。如:

       

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. def fac(n:Int):Int = if( n <= 01 else n*fac(n-1)  
    2.   
    3. println(fac(5)) //120  
       

    默认參数和代码參数:

         

    有些情况下我们不须要给出所有參数,相应这类函数我们能够使用默认參数。当然你须要知道參数顺序或者參数名称。如:

             

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. def outputBookName(bookname:String,left:String="{",right:String="}") =  
    2.   left + bookname + right  
    3.   
    4. println(outputBookName("book1"))  
    5.   
    6. println(outputBookName("book2""[""]"))  
    7.   
    8. println(outputBookName(right="***]",bookname="book3"))  
     输出:

           {book1}   --》使用了默认參数
            [book2]    --》 使用了传入的參数
            {book3***] --》依据须要,提供參数名称和值替换默认值


    变长參数:

          实现一个能够接受可变长度的參数列表的函数,如:

        

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. def sum1(args : Int*) = {  
    2.      var result = 0  
    3.      for(arg <- args)  
    4.         result += arg  
    5.         result  
    6.    }  
    7.      
    8.    println(sum1(5,4,3,2,1)) //15  
     

       实现一个序列作为參数传入上述函数中。须要追加 _*,告诉编译器希望把这个參数当做序列处理。如:

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. val s = sum1(1 to 5: _*)  //将1到5当做參数序列处理  

     在递归中我们相同能够使用这样的方式。如:

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. def sum2(args : Int*):Int = {  
    2.       if(args.length == 0 )  
    3.         0  
    4.       else  
    5.         args.head + sum2(args.tail: _*)  
    6.    }  
    7.      
     序列的head是參数args的首个元素,而tail是全部其他的元素序列,这是个Seq,须要用 _*将它转为參数序列。



    过程:

       定义:

        Scala对不返回值的函数有特殊的表示法。

    假设函数体包括在花括号里但没有前面的=号,那么返回类型是Unit。这种函数叫做过程。

    过程不返回值。我们调用它是为了使用它的副作用。

    如:我们须要打印一些图案,那么能够定义一个过程:

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1.     def draw(s:String) {  
    2.         
    3.       println("-------")  
    4.       println("|"+"   "+"|")  
    5.       println("|"+s+"|")  
    6.       println("|"+"   "+"|")  
    7.       println("-------")  
    8.     }  
    9.       
    10.     println(draw("123"));  
    11.   
    12. 输出:  
    13.   
    14. -------  
    15. |   |  
    16. |123|  
    17. |   |  
    18. -------  
    19. ()  

    看上面的返回,能够明显的指定这个函数的返回值是Unit;


    懒值:

         当val被声明为lazy时。它的初始化将被推迟。知道我们首次取它的值。

    如:

        

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. lazy val file1 = scala.io.Source.fromFile("C:/hello.scala").mkString  
    2.   
    3. println(file1)   
    输出:

    println("hello")


    假设我们不调用

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. println(file1)   

      这行语句,即file1不被訪问,那么文件就不会被打开。

        

    异常:


     Scala异常的工作机制同Java。当你须要抛出异常时,如:

       throw new FileNotFoundException("系统找不到指定的文件。")

    Scala异常同Java一样,抛出的异常必须是java.lang.Throwable的子类。

    其与Java不同的是,Scala没有受检异常。不须要声明函数或者方法可能会抛出异常。


    throw 表达式有特殊类型Nothing。这在if else表达式中非常实用。假设一个分支的类型是Nothing,那么if else表达式的类型就是另外一个分支的类型。


    捕获异常的语法採用模式匹配的语法。如:




    try finally语句能够释放资源,不论是否发生异常。如:


    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. var in = new URL("http://ubmcmm.baidustatic.com/media/v1/0f0000g0bymVB3uhUffi-0.gif").openStream();  
    2.      
    3.    try {  
    4.      process(in)  
    5.    }finally {  
    6.      in.close()  
    7.    }  
    8.      
    9.    def process(in:java.io.InputStream) = {  
    10.        
    11.      println(in.toString());  
    12.        
    13.    }  

    输出:sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@8b33e8



    以上借鉴http://blog.csdn.net/wangmuming/article/details/35226275




  • 相关阅读:
    (杭电 1014)Uniform Generator
    错排公式浅谈(推导+应用)
    (杭电 2045)不容易系列之(3)—— LELE的RPG难题
    (杭电 2046)骨牌铺方格
    (补题 杭电 2044)一只小蜜蜂...
    (杭电 1097)A hard puzzle
    Linux内核实验作业六
    《Linux内核设计与实现》第十八章读书笔记
    实验作业:使gdb跟踪分析一个系统调用内核函数
    k8s标签
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/7288911.html
Copyright © 2020-2023  润新知