zoukankan      html  css  js  c++  java
  • Spark记录-Scala函数与闭包

    函数声明

    Scala函数声明具有以下形式 -

    def functionName ([list of parameters]) : [return type]
    
    Scala

    如果不使用等号和方法体,则隐式声明抽象(abstract)方法。

    函数定义

    Scala函数定义具有以下形式 -

    语法

    def functionName ([list of parameters]) : [return type] = {
       function body
       return [expr]
    }
    
    Scala

    这里,返回类型可以是任何有效的Scala数据类型,参数列表将是由逗号分隔的变量列表,参数列表和返回类型是可选的。与Java非常相似,返回语句可以与表达式一起使用,以防函数返回值。 以下是将两个整数相加并返回其总和的函数,

    语法

    object add {
       def addInt( a:Int, b:Int ) : Int = {
          var sum:Int = 0
          sum = a + b
          return sum
       }
    }
    
    Scala

    一个不返回任何东西的函数可以返回一个类似在Java中的void类型,并表示该函数不返回任何内容。 在Scala中不返回任何东西的函数称为过程。

    语法

    object Hello{
       def printMe( ) : Unit = {
          println("Hello, Scala!")
       }
    }
    
    Scala

    调用函数

    Scala为调用方法提供了许多句法变体。以下是调用方法的标准方法 -

    functionName( list of parameters )
    
    Scala

    如果使用对象的实例调用函数,那么可使用与Java类似的点符号,如下所示:

    [instance.]functionName( list of parameters )
    
    Scala

    尝试以下示例程序来定义并调用相同的函数 -

    示例 -

    object Demo {
       def main(args: Array[String]) {
          println( "Returned Value : " + addInt(5,7) );
       }
    
       def addInt( a:Int, b:Int ) : Int = {
          var sum:Int = 0
          sum = a + b
    
          return sum
       }
    }
    
    Scala

    将上述程序保存在源文件:Demo.scala中,使用以下命令编译和执行此程序。

    Scala函数是Scala编程的核心,因此Scala被认为是函数式编程语言。以下是与Scala函数相关的几个重要概念,Scala程序员应该要理解。

    Scala按名称调用函数

    object Demo {
       def main(args: Array[String]) {
            delayed(time());
       }
    
       def time() = {
          println("Getting time in nano seconds")
          System.nanoTime
       }
       def delayed( t: => Long ) = {
          println("In delayed method")
          println("Param: " + t)
       }
    }

    Scala命名参数的函数

    在正常的函数调用中,调用的参数按照被调用函数定义的参数顺序逐个匹配。命名参数允许您以不同的顺序将参数传递给函数。语法只是每个参数前面都有一个参数名称和一个等号。

    尝试以下程序,它是一个简单的例子来显示具有命名参数的函数。

    object Demo {
       def main(args: Array[String]) {
          printInt(b = 5, a = 7);
       }
    
       def printInt( a:Int, b:Int ) = {
          println("Value of a : " + a );
          println("Value of b : " + b );
       }
    }
    
    Scala

    将上述程序保存在源文件:Demo.scala中,使用以下命令编译和执行此程序。

    Scala可变参数的函数

    Scala允许指定函数的最后一个参数可重复。 这允许客户端将可变长度参数列表传递给函数。 这里,打印字符串函数里面的args类型,被声明为类型String *,实际上是Array [String]

    尝试以下程序,这是一个简单的例子来演示如何使用带有可变参数的函数。

    object Demo {
       def main(args: Array[String]) {
          printStrings("Hello", "Scala", "Python");
       }
    
       def printStrings( args:String* ) = {
          var i : Int = 0;
    
          for( arg <- args ){
             println("Arg value[" + i + "] = " + arg );
             i = i + 1;
          }
       }
    }

    Scala递归函数

    递归在纯功能编程中起着重要作用,Scala支持递归函数。 递归表示一个函数可以重复调用自身。

    尝试以下程序,它是一个很好的递归示例,它计算给定参数(数字)的阶乘。

    示例

    object Demo {
       def main(args: Array[String]) {
          for (i <- 1 to 10)
             println( "Factorial of " + i + ": = " + factorial(i) )
       }
    
       def factorial(n: BigInt): BigInt = {  
          if (n <= 1)
             1  
          else    
          n * factorial(n - 1)
       }
    }

    Scala递归函数

    Scala允许您指定函数参数的默认值。 这样一个参数可以从函数调用中选择性地省略,在这种情况下,相应的参数值将使用默认值。如果指定其中一个参数,则使用该参数将传递第一个参数,第二个参数将从默认值中获取。

    尝试以下示例,它是为函数指定默认参数的示例 -

    示例

    object Demo {
       def main(args: Array[String]) {
          println( "Returned Value : " + addInt() );
       }
    
       def addInt( a:Int = 5, b:Int = 7 ) : Int = {
          var sum:Int = 0
          sum = a + b
    
          return sum
       }
    }

    Scala高阶函数

    Scala允许定义高阶函数。它是将其他函数作为参数或其结果是函数的函数。

    尝试以下示例程序,apply()函数接受另一个函数f和值v,并将函数f应用于v

    示例

    object Demo {
       def main(args: Array[String]) {
          println( apply( layout, 10) )
       }
    
       def apply(f: Int => String, v: Int) = f(v)
    
       def layout[A](x: A) = "[" + x.toString() + "]"
    }

    Scala嵌套函数

    Scala允许您定义函数内部的函数,而在其他函数中定义的函数称为局部函数。这是一个阶乘计算器的实现,我们使用传统的技术来调用第二个嵌套方法来完成工作。

    尝试以下程序来了解如何实现嵌套函数。

    示例

    object Demo {
       def main(args: Array[String]) {
          println( factorial(0) )
          println( factorial(1) )
          println( factorial(2) )
          println( factorial(3) )
       }
    
       def factorial(i: Int): Int = {
          def fact(i: Int, accumulator: Int): Int = {
             if (i <= 1)
                accumulator
             else
                fact(i - 1, i * accumulator)
          }
          fact(i, 1)
       }
    }

    Scala匿名函数

    Scala提供了一个相对轻量级的语法来定义匿名函数。源代码中的匿名函数称为函数文字,在运行时,函数文字被实例化为称为函数值的对象。

    Scala支持一级函数,函数可以用函数文字语法表达,即(x:Int)=> x + 1,该函数可以由一个叫作函数值的对象来表示。

    尝试以下表达式,它为整数创建一个后继函数 -

    var inc = (x:Int) => x+1
    
    Scala

    变量inc现在是一种可以像函数那样使用的函数 -

    var x = inc(7)-1
    
    Scala

    还可以如下定义具有多个参数的函数:

    var mul = (x: Int, y: Int) => x*y
    
    Scala

    变量mul现在是可以像函数那样使用的函数 -

    println(mul(3, 4))
    
    Scala

    也可以定义不带参数的函数,如下所示:

    var userDir = () => { System.getProperty("user.dir") }
    
    Scala

    变量userDir现在是可以像函数那样使用的函数 -

    println( userDir )

    Scala部分应用函数

    当在调用一个函数时,把这个函数应用到参数中。 如果您传递所有预期的参数,则表示您已完全应用它。 如果只传递几个参数并不是全部参数,那么将返回部分应用的函数。这样就可以方便地绑定一些参数,其余的参数可稍后填写补上。

    尝试以下,下面是一个简单的示例程序用来演示如何使用部分应用函数 -

    import java.util.Date
    
    object Demo {
       def main(args: Array[String]) {
          val date = new Date
          log(date, "message1" )
    
          Thread.sleep(1000)
          log(date, "message2" )
    
          Thread.sleep(1000)
          log(date, "message3" )
       }
    
       def log(date: Date, message: String)  = {
          println(date + "----" + message)
       }
    }
    
    Scala

    将上述程序保存在源文件:Demo.scala 中,使用以下命令编译和执行此程序。

    D:/> scalac Demo.scala
    D:/> scala Demo
    
    Mon Dec 02 12:52:41 CST 2018----message1
    Mon Dec 02 12:52:41 CST 2018----message2
    Mon Dec 02 12:52:41 CST 2018----message3
    
    Scala

    这里,log()方法有两个参数:datemessage。 我们想要多次调用该方法,具有相同的日期值,但不同的消息值。可以通过将参数部分地应用到log()方法来消除将日期传递给每个调用的干扰。为此,首先将值绑定到date参数,并将第二个参数绑定到其位置。 结果是存储在变量中的部分应用函数。

    尝试以下示例程序以仅使用未绑定的参数消息来调用此新方法。

    import java.util.Date
    
    object Demo {
       def main(args: Array[String]) {
          val date = new Date
          val logWithDateBound = log(date, _ : String)
    
          logWithDateBound("message1" )
          Thread.sleep(1000)
    
          logWithDateBound("message2" )
          Thread.sleep(1000)
    
          logWithDateBound("message3" )
       }
    
       def log(date: Date, message: String) = {
          println(date + "----" + message)
       }
    }
    
    Scala

    将上述程序保存在源文件:Demo.scala中,使用以下命令来编译和执行此程序。

    D:>scalac Demo.scala
    D:>scala Demo
    
    Mon Dec 02 12:53:56 CST 2018----message1
    Mon Dec 02 12:53:56 CST 2018----message2
    Mon Dec 02 12:53:56 CST 2018----message3

    Scala柯里化函数

    柯里化(Currying)函数是一个带有多个参数,并引入到一个函数链中的函数,每个函数都使用一个参数。 柯里化(Currying)函数用多个参数表定义,如下所示:

    def strcat(s1: String)(s2: String) = s1 + s2
    
    Scala

    或者,还可以使用以下语法定义柯里化(Currying)函数 -

    def strcat(s1: String) = (s2: String) => s1 + s2
    
    Scala

    以下是调用柯里化(Currying)函数的语法 -

    strcat("foo")("bar")
    
    Scala

    您可以根据需要在柯里化(Currying)函数上定义两个以上的参数。尝试下面一个简单的示例程序用来了解如何使用柯里化(Currying)函数 -

    object Demo {
       def main(args: Array[String]) {
          val str1:String = "Hello, "
          val str2:String = "Scala!"
    
          println( "str1 + str2 = " +  strcat(str1)(str2) )
       }
    
       def strcat(s1: String)(s2: String) = {
          s1 + s2
       }
    }
    
    Scala

    将上述程序保存在源文件:Demo.scala 中,使用以下命令编译和执行此程序。

    D:> scalac Demo.scala
    D:> scala Demo
    
    str1 + str2 = Hello, Scala!

    Scala闭包

    闭包是一个函数,它返回值取决于在此函数之外声明的一个或多个变量的值。

    以下代码是一个匿名函数。

    val multiplier = (i:Int) => i * 10
    
    Scala

    这里,函数体i * 10中使用的唯一变量是i,它被定义为该函数的一个参数。尝试以下代码 -

    val multiplier = (i:Int) => i * factor
    
    Scala

    乘数有两个自由变量:ifactori是函数的一个正式参数。 因此,每当调用乘数时,它必然会有一个新的值。然而,factor不是一个正式的参数,那这是什么呢? 再增加一行代码。

    var factor = 3
    val multiplier = (i:Int) => i * factor
    
    Scala

    现在factor参考了函数之外的变量,但是在闭合的范围内。函数引用factor,每次读取其当前值。 如果函数没有外部引用,那么它本身就会被简单地关闭,不需要外部上下文。

    请尝试以下示例程序 -

    object Demo {
       def main(args: Array[String]) {
          println( "multiplier(1) value = " +  multiplier(1) )
          println( "multiplier(2) value = " +  multiplier(2) )
       }
       var factor = 3
       val multiplier = (i:Int) => i * factor
    }
    
    Scala

    将上述程序保存在源代码:Demo.scala中,使用以下命令编译和执行此程序。

    D:>scalac Demo.scala
    D:>scala Demo
    
    multiplier(1) value = 3
    multiplier(2) value = 6
  • 相关阅读:
    VMware Workstation Pro下载密钥
    hypervisor
    Xmanager6 下载地址
    linux常用命令
    linux常用
    查看机器端口信息
    windows下快捷键
    SpringMVC学习笔记整理
    2017面试题收集
    oracle 常用知识点整理
  • 原文地址:https://www.cnblogs.com/xinfang520/p/7727934.html
Copyright © 2011-2022 走看看