zoukankan      html  css  js  c++  java
  • Scala学习笔记(2)

    一、控制结构和函数

    ---------------------------------------------------------------

    1、条件表达式

     (1) 在Scala中if/else的表达式都是有值的,这个值就是跟在if或者else之后的表达是的值

      eg: if(x >0) 1 else -1  //上面表达式的值是1或者-1,具体是哪个值取决于x的值

      

     (2) 可以将if/else表达式的值赋给变量

      val s = if (x > 0) 1 else -1   <===>if(x>0) s = 1 else s =-1  //相对而言,前面的一种写法会更好,因为其可以用来初始化一个val,而在后面的s必须是var类型,这个地方x是常量不能再进行赋值了

      java表达式:x>0?1 : -1    //Java或C++  <===>if(x > 0 )1 else -1

      (3)在Scala中,每个表达式都有一个类型。举例来说,表达式if(x>0) 1 else -1 的类型是Int,因为这里的两个表达式都是Int

        而:if (x>0) "positive" else -1   //这个表达式的类型是两个分支类型的公共超类。这里第一个分支是java.lang.String

        而另外一个 分支是Int类型。所以这里的公共超类是Any

        这里如果else部分缺失了:if (x>0) 1    //那么有可能if语句没有输出值。但是在Scal中,每个表达式都应该有某种值,这个问题的解决方案是引入一个Unit类,写作()。

        不带else的if语句等同于if (x> 0 ) 1 else ()  //()表示的是"无有用值"的占位符,可以将Unit当做Java或C++中的void

      (4)注意:REPL比起编译器来更加的"近视",在同一时间只能看到一行代码。

          eg: if(x>0) 1

            else if (x==0) 0 else -1    //这里REPL会执行if(x>0) 1 ,然后就显示结果,而之后看到接下来的    else    关    键    字  就会不知所措

        如果想在else前面换行的话,需要用到花括号

        if(x > 0){1

          } else if (x==0) 0 else -1 

        如果想在REPL中粘贴成块的代码,而又不想近视问题,可以使用粘贴模式。键入:paste,把近视代码粘贴进去,然后按下Ctrl + D。这样REPL会把整个代码块当做一个整体来进行分析

      (5)条件表达式,scala的表达式有值,是最后一条语句的值

        scala>val x =1 ;

        scala > val b = if (x>0) 1 else -1 ;

      (6)val xx = if(x>0) 1 else "hello"  //这个地方的返回值是Any类型  xx:Any =1,Any是Int和String的创造类

        参数的强转: 1.toString    //将数值类型的转换成字符串类型String类型  

              "1000".toInt   //将字符串类型转换成Int类型

      (7)赋值语:val y = (s =1 )    //赋值语句为空,y:Unit =()  类似于java中的void

      (8)粘贴模式:scala>:paste

              if(x>0) {

               1  } else -1

    //      ctrl + D  //退出粘贴模式

      (8)java语言的编码运行过程:*.java ----->*.class----------->程序

    2、语句终止:Scala与其他的脚本语言相类似,行尾的位置不需要分号。在}、else以及类似的位置也不需要写分号,只要能从上下文明确的判断出这里是语句的终止就可以

      (1)如果在单行中能够写下多个语句,就需要用分号将他们分割开来

        if ( n > 0 ) {r = r * n ; n-=1}

      (2)如果写较长的语句,需要分成两行来写的话,就需要确保第一行以一个不能用作语句结尾的符号作为结尾,一般来说是比较好的选择是操作符:

      s = s0 +(v - v0)* t +

        0.5*(a-a0)*t*t

      (3)Scala程序员们更加倾向于使用花括号来进行相关的处理:

        if(n > 0){

          r = r*n

          n -=1

         }      //这个地方可以知道,以{结束的行很清楚的表示了后面还有很多的内容

    3.块表达式和赋值

      在java中快语句是包含在{}中的语句序列。当需要在逻辑分支或循环中放置多个动作的时候,可以使用快语句。

      在Scala中,{}块包含一系列的表达式,结果也是一个表达式。快中最后一个表达式的值就是块的值

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

      {}块的取值取其最后一个表达式,在此处粗体标出。变量dx和dy仅作为计算所需的中间值

      在Scala中,赋值动作本身是没有值的,或者说,他们的值是Unit类型的,Unit类型等价于java中的void,而这个类型只有一个值,写作()。一个以赋值语句结束的块,比如{r =r * n; n -=1)的值是Unit类型的

       Unit<===>void

    4、输入和输出

      (1).打印一个值,需要用print或者println函数进行相关的打印,而后者在打印完成后会追加一个换行符。

        print("answer:")    //打印

        println(43)      //换行打印

      //输出

      Scala>print("hellp")

      Scala>println("hello")

      Scala>val password = readLine("请输入密码");

    5、循环

      Scala拥有和java相同的while和do循环

      通过粘贴模式来写循环。(while)

    var i = 0;
    while
    (n>0){ r= r*n n-=1 }

    通过Scala语言打印出99乘法表

      

    var i = 1;
    while(i<10){
      var j = 1;
      while(j<=i){
      print(i+"*"+j+"="+(i*j)+"    ");
      j+=1;          
      }     
      println();
      i+=1;       
    }

      百钱买百鸡问题

    //百钱买白鸡
    100块钱买100只小鸡
    公鸡:5块钱/只
    母鸡:3块钱/只
    小鸡:1块钱/3只

    var cock=0;
    while(cock <= 20){
    var hen = 0 ;
    while(hen <=100/3){
    var chicken =0;
    while(chicken<=100){
    var money=cock*5 + hen*3 +chicken*(1/3);
    var mount = cock + hen + chicken;
    if(money==100 && mount==100){
    println("cock:"+cock+","+"hen:"+hen+","+"chicken:"+chicken);
    }
    chicken+=3;
    }
    hen+=1;
    }
    cock+=1;
    }

    
    
     

    Scala加载Scala类的方法:load d:scalauy.scala

      (2)for循环

      

    for(x<-1 to 10) println(x)
    语法:
        for(i<- 表达式)    //这个地方1 to n 这个调用返回1到n之间的区间的Range
    //让变量i便利<-右边的表达式的所有制。至于这个便利具体如何执行,取决于表达式的类型。

      在便利字符串或者数组的时候,通常需要使用0到n-1的区间。这个时候可以用util方法而不是to方法。util方法返回一个并不包含上限的区间。

      

    val s ="hello"
    var sum = 0
    for(i <- 0 util s.length){    sum +=s(i)}
    println(sum);
      

    可以使用breaks对象的break方法

    6、可以使用变量<-表达式的形式提供多个生成器,用分号将其分隔开来。

      for高级循环

    for(i<- 1 to 3 ;j<- 1 to 3) println((10*i+j)+" ")

      这个地方每一个生成器都可以带一个守卫,以if开头的Boolean表达式:

      

    for(i<- 1 to 3 ; j <- 1 to 3 if i!=j) print((10*i+j)+" ")

    如果for循环的循环体外面以yield开始,则循环会构造一个集合,每次都迭代集合中的一个值

      

    for(i < -1 to 10) yeild i%3   //这样的for循环叫做for循环推倒式

    7、函数

    Scala除了方法之外还支持函数。方法对对象进行操作,函数不是,如果要定义函数,需要给出函数的名称、参数和函数体

      

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

    如果函数体需要多个表达式完成,可以用代码块。快中最后一个表达式就是函数的返回值。

    def fac(n:Int)={
        var r =1
        for(i<- 1 to n) r= r*i
        r
       }

    本例中返回值是r,但是没有return 这个关键词

    但是对于递归函数,我们必须制定返回值类型。

      def fac(n:Int):Int=if(n<=0) 1 else n*fac(n-1)  //这个地方的递归函数必须制定返回值类型,如果没有进行指定,Scala编译器就没有办法校验n*fac(n-1)的数据类型了

      定义函数:

      def add (a:Int,b:Int):Int = {

        var c =a+b ;

        return c;

    }

    在:paste模式下进行粘贴,最后会得到add(a:Int,b:Int)Int,即是参数类型是Int型,返回值类型也是Int型

      定义递归:

      def fac(n:Int):Int= if(n==1) 1 else n*fac(n-1);    //定义了n的阶乘,递归的函数必须显示定义返回值类型

      8.默认参数和带名参数

      (1)eg:def decorate(str:String,left:String="[",right:String="]")= left+str+right;

      如果调用decorate("hello")  ===>["Hello"]

      或者:def decorate(prefix:String,str:String,suffix:String)={  //默认不带参

        prefix+str+suffix    

      }

      //这个地方的调用:最少要带上两个参数,decorate("hello","world");最终把最后的括号带上了

      //或者指定给哪个参数进行传参,decorate(str="hello")

      //或者给其他的参数进行相关的传参:scala>decorate(str="hello",prefix="<<"。最后的返回值是<<hello[]]

      def decorate(prefix:String="[[",str:String,suffix:String="]]")={  //默认带参数的

        prefix+ str+suffix

      }

      调用函数decorate("[[","hello","]]") ==============>[[hello]]

      (2)如果相对参数的数量的值不够,参数会从后面诸葛应用进来,如decorate("Hello",">>>")会使用right参数的默认值,

       得到">>>[Hello]"

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

      (3)在提供参数值的时候指定参数名。如:

        decorate(left="<<<",str="Hello",right=">>>")    //最后的结果是<<<Hello>>>

      (4)带名参数可以让函数更加可读。

      (5)函数的默认值和命名参数

        scala>def decorate(prefix:String,str:String,suffix:String)={

          prefix + str +sufix

      }

    9.变长参数

     (1)边长参数用法例子 

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

      val s = sum(1,4,9,16,25)  //这个地方函数得到的是一个类型为Seq的参数

      (2)如果已经有一个值的序列,则不能直接将其传入函数。如:var s =sum(1 to 5)  //错误

      val s = sum (1 to 5)  //错误,这个地方要注意,如果sum函数传入的是单个参数,那么参数必须是单个的整数,而不是一个整个的区间。解决的办法是告诉编译器,希望这个参数被当做参数序列进行处理。追加:_*,如下所示:

      val s =sum(1 to 5:_*)  //这个地方将1 to 5当做参数序列进行处理

      (3)在递归定义中会用到上面的语法:

        def recursiveSum(args:Int*):Int={    //在这里序列head是首个元素,而tail是所有其他元素的序列,这又是一个Seq,我们用_*来转换成参数序列

          if(args.length==0) 0 

          else args.head + recursiveSum(args:tail:_*)

      }

      

      (4)参数当做参数序列进行处理

    def sum1(args:Int*):Int={
        if(args.length==0) 0
        else args.head+sum1(args.tail_*)
    }

    scala>add(1 to 10)    //错误

    scala>add(1 to 10:_*)  //将1 to 10当做序列

    10.过程:如果函数体包含在花括号中但是没有前面的=号,那么返回值类型就是Util。这样的函数成为过程

        过程不返回值,我们调用它仅仅是为了副作用

        (1)也可以进行这样的方式进行相关的定义:def box(s:String):Unit={

            ................

          }

    def box(s:String){    //仔细看:这个地方没有=号
        var border="-" * s.length +"--
    "
        println(border+"|"+s+"
    "+border)
    }

    11.懒值

      当val被声明为lazy的时候,它的初始值将被推迟,知道我们首次对其进行取值

      lazy val words = 

    12.异常处理

      try{

        "hello".toInt;

      }catch{

        case _:Exception =>print("xxx");

        case ex:java.io.IOException=>print(ex)

      }

      _      //通配符

      java.io._    //通配相当于*

      :_*      //1 to10:_*,转成序列

  • 相关阅读:
    CodeForces Gym 100500A A. Poetry Challenge DFS
    CDOJ 486 Good Morning 傻逼题
    CDOJ 483 Data Structure Problem DFS
    CDOJ 482 Charitable Exchange bfs
    CDOJ 481 Apparent Magnitude 水题
    Codeforces Gym 100637G G. #TheDress 暴力
    Gym 100637F F. The Pool for Lucky Ones 暴力
    Codeforces Gym 100637B B. Lunch 找规律
    Codeforces Gym 100637A A. Nano alarm-clocks 前缀和
    TC SRM 663 div2 B AABB 逆推
  • 原文地址:https://www.cnblogs.com/bigdata-stone/p/9632631.html
Copyright © 2011-2022 走看看