• 2、函数入门


    一、函数入门

    1、定义函数

    在Scala中定义函数时,需要定义函数的函数名、参数、函数体。
    
    我们的第一个函数如下所示:
      def sayHello(name:String,age:Int)= {
        if(age>18){printf("hi %s,you are a big boy
    ",name); age}
       else{printf("hi %s,you are a little boy
    ",name);age}
    
    Scala要求必须给出所有参数的类型,但是不一定给出函数返回值的类型,只要右侧的函数体中不包含递归的语句,Scala就可以自己根据右侧的表达式推断出返回类型。
    
    
    
    #########
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    def sayHello(name:String, age:Int) = {
     if(age >= 18) {
      printf("Hi, %s, you are a big boy!
    ", name)
      age
     } else {
      printf("Hi, %s, you are a little boy!
    ", name)
      age
     }
    }
    
    // Exiting paste mode, now interpreting.
    
    sayHello: (name: String, age: Int)Int
    
    
    scala> sayHello("leo", 30)
    Hi, leo, you are a big boy!
    res40: Int = 30

    2、在代码块中定义函数

    单行的函数:def sayHello(name:String)= print("Hello,"+name)
    
    如果函数体中有多行代码,则可以使用代码块的方式包裹多行代码,代码块中最后一行的返回值就是整个函数的返回值。
    与Java中不同,不是使用return返回值的。
    
    比如如下的函数,实现累加的功能:
    def sum(n:Int)= {
      var sum=0;
      for(i<- 1 to n)sum+=i 
      sum
    }
    
    
    ######
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    def sum(n:Int) = {        #写=时,函数要有返回值
     var result =0 
     for(i <- 1 to n) {
      result += i
     }
     result
    }
    
    // Exiting paste mode, now interpreting.
    
    sum: (n: Int)Int
    
    
    scala> sum(10)
    res41: Int = 55

    3、递归函数

    如果在函数体内递归调用函数自身,则必须手动给出函数的返回类型。
    
    例如,实现经典的斐波那契数列:
    def fab(n:Int): Int = {    #第二个Int是返回类型
    if(n <= 1)1
    else fab(n-1)+ fab(n-2)
    }

    二、默认参数和带名参数

    1、默认参数

    在Scala中,有时我们调用某些函数时,不希望给出参数的具体值,而希望使用参数自身默认的值,此时就定义在定义函数时使用默认参数。
    
    def sayHello(firstName:String,middleName:String="William",
    lastName:String="Croft")= firstName + " " + middleName +" " +
    lastName
    
    如果给出的参数不够,则会从作往右依次应用参数。
    
    
    
    
    ####
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    def sayHello(name: String, age: Int = 20) {
     print("Hello, " + name + ", you age is " + age)
    }
    
    // Exiting paste mode, now interpreting.
    
    sayHello: (name: String, age: Int)Unit
    
    scala> sayHello("leo")
    Hello, leo, you age is 20
    scala> sayHello("leo",30)
    Hello, leo, you age is 30

    2、带名参数

    在调用函数时,也可以不按照函数定义的参数顺序来传递参数,而是使用带名参数的方式来传递。
    
    sayHello(firstName="Mick",lastName ="Nina",middleName="Jack")
    
    还可以混合使用未命名参数和带名参数,但是未命名参数必须排在带名参数前面。
    
    sayHello("Mick",lastName="Nina",middleName ="Jack")
    
    
    
    #####

    三、变长参数

    1、变长参数

    在Scala中,有时我们需要将函数定义为参数个数可变的形式,则此时可以使用变长参数定义函数。
    def sum(nums:Int*)= {
      var res = 0
      for(num <- nums)res += num
      res
    }
    
    
    
    #######
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    def sum(nums: Int*) = {
     var result = 0
     for(num <- nums) {
      result += num
     }
     result
    }
    
    // Exiting paste mode, now interpreting.
    
    sum: (nums: Int*)Int
    
    scala> sum(1,2,3,4,5)
    res44: Int = 15

    2、使用序列调用变长参数

    在如果想要将一个已有的序列直接调用变长参数函数,是不对的。比如val s=sum(1 to 5)。
    此时需要使用Scala特殊的语法将参数定义为序列,让Scala解释器能够识别。这种语法非常有用!一定要好好主意,在spark的源码中大量地使用到了。
    
    val s = sum(1 to 5:_*)
    
    案例:使用递归函数实现累加
    
    def sum2(nums:Int*):Int = {
      if(nums.length==0)0
      else nums.head + sum2(nums.tail:_*)
    }
    
    
    
    ########
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    def sum(nums: Int*) = {
     var result = 0
     for(num <- nums) {
      result += num
     }
     result
    }
    
    // Exiting paste mode, now interpreting.
    
    sum: (nums: Int*)Int
    
    
    scala> sum(1 to 5: _*)
    res45: Int = 15
    
    直接写sum(1 to 5)会报错,所以要用 _*将1 to 5转化为参数序列
    ## scala> :paste // Entering paste mode (ctrl-D to finish) def sum2(nums: Int*): Int = { if(nums.length == 0) 0 else nums.head + sum2(nums.tail: _*) } // Exiting paste mode, now interpreting. sum2: (nums: Int*)Int scala> sum2(1,2,3,4,5) res46: Int = 15

    四、过程、lazy值和异常

    1、过程

    在Scala中,定义函数时,如果函数体直接包裹在了花括号里面,而没有使用=连接,则函数的返回值类型就是Unit。这样的函数就被称之为过程。
    过程通常用于不需要返回值的函数。
    
    过程还有一种写法,就是将函数的返回值类型定义为Unit。
    
    def sayHello(name:String)="Hello,"+name 
    def sayHello(name:String){print("Hello,"+name);"Hello,"+name}
    def sayHello(name:String):Unit="Hello,"+name
    
    
    
    
    ######
    scala> def sayHello(name: String) {print("hello, " + name); "Hello, " + name}
    sayHello: (name: String)Unit
    
    scala> sayHello("leo")
    hello, leo
    
    
    scala> def sayHello(name: String) = {print("hello, " + name); "Hello, " + name}
    sayHello: (name: String)String
    
    scala> sayHello("leo")
    hello, leores48: String = Hello, leo
    
    
    scala> def sayHello(name: String): Unit = "Hello, " + name
    sayHello: (name: String)Unit
    
    scala> sayHello("leo")
    
    scala>

    2、lazy值

    在Scala中,提供了lazy值的特性,也就是说,如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会发生计算。
    这种特性对于特别耗时的计算操作特别有用,比如打开文件进行lO,进行网络lO等。
    
    import scala.io.Source._
    lazy val lines=fromFile("C:/Users/Administrator/Desktop/test.txt").mkString
    
    即使文件不存在,也不会报错,只有第一个使用变量时会报错,证明了表达式计算的lazy特性。
    
    val lines=fromFile("C://Users//Administrator/Desktop/test.txt").mkString 
    lazy val lines=fromFile("C://Users/Administrator//Desktop/test.txt").mkString
    def lines = fromFile("C://Users/Administrator/Desktop/test. txt"). mkString
    
    
    
    
    #######
    scala> lazy val lines = fromFile("//home//test.txt").mkString
    lines: String = <lazy>
    
    scala> print(lines)
    Hello Word

    3、异常

    在Scala中,异常处理和捕获机制与Java是非常相似的。
    
    try{
      throw new lllegalArgumentException("x should not be negative")
    }catch{
      case _:lllegalArgumentException => printin("lllegal Argument!")
    }finally{
      print("release resources!")
    
    
    
    #############
  • 相关阅读:
    将所有程序设置XML集中到一个单独XML配置文件的方法:使用appSettings元素的configSource元素
    MVC中JQuery文件引入的路径问题,@Url.Content函数
    EF的表连接方法Include()
    在使用EFCodeFirst中出现类型“System.Data.Objects.ObjectContext”在未被引用的程序集中定义的解决方案
    总结下遇到的C#新语法
    MVC3下的layout页面
    C#委托初探
    WebBrowser Control
    Python之面向对象二
    Python之面向对象一
  • 原文地址:https://www.cnblogs.com/weiyiming007/p/10954018.html
Copyright © 2020-2023  润新知