zoukankan      html  css  js  c++  java
  • Scala学习笔记-3-函数

    package day04
    
    import java.io.{File, PrintWriter}
    
    class Demo(desc: String) {
    
      override def toString: String = desc
    }
    
    object Demo {
    
      def main(args: Array[String]): Unit = {
    
        val d = new Demo("Scala 函数")
        println(d)
    
        test_1()
    
        test_2()
    
        test_3()
    
        test_4()
    
        test_5()
    
        // test_6()
    
        test_7()
    
        test_8()
    
        test_9()
    
        test_10()
      }
    
      // 类成员函数,和 Java 的成员方法一致,略
    
      /**
        * 局部函数:在函数内部定义函数
        * 在局部函数中可以访问外部定义的变量
        *
        */
      def test_1(): Unit = {
        val v_1 = "hello "
    
        def innerFun(): Unit = {
          println(v_1 + "inner function")
        }
    
        innerFun()
      }
    
      /**
        * 函数字面量(就是匿名函数)
        * 函数是 Scala 中的“头等公民”(W3C中这句话不知道什么意思。。。)
        * 匿名函数看起来不能指定返回值类型(语句最后一行执行的结果就是返回值)
        */
      def test_2(): Unit = {
    
        // 函数字面量
        var increase = (x: Int) => x + 1
        println(increase(6))
    
        // Lists 不可修改序列
        val someNumbers = List(-11, -10, -5, 0, 5, 10)
    
        // 在 foreach 中使用匿名函数
        someNumbers.foreach(i => println(i))
    
        // 在 filter 中使用匿名函数
        println(someNumbers.filter(i => i > 0))
      }
    
      /**
        * 部分应用的函数(其实就是 python 中的偏函数)
        */
      def test_3(): Unit = {
    
        // sum2 是 sum1 的简化写法
        // Scala 允许使用“占位符”下划线”_”来替代一个或多个参数,只要这个参数值函数定义中只出现一次,Scala编译器可以推断出参数。
        def sum1 = (a: Int, b: Int, c: Int) => a + b + c
    
        def sum2 = (_: Int) + (_: Int) + (_: Int)
    
    
        // 定义偏函数
        val b = sum2(1, _: Int, 3)
    
        println(b(10))
      }
    
    
      // 闭包
      def test_4(): Unit = {
    
        var more = 1
    
        // 定义:引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。
        val addMore1 = (i: Int) => i + more
        println(addMore1(10))
    
        // 当这个自由变量发生变化时,Scala 的闭包能够捕获到这个变化,因此 Scala 的闭包捕获的是变量本身而不是当时变量的值。
        more = 100
        println(addMore1(10))
    
        // 如果变量在闭包在发生变化,也会反映到函数外面定义的闭包的值。
        val addMore2 = (i: Int) => {
          more = more + i
          more
        }
        println(addMore2(1000))
        println(addMore2(1000))
        println(more)
      }
    
      // 函数–可变参数,命名参数,缺省参数
      def test_5(): Unit = {
    
        // 可变参数
        def echo(args: String*): Unit = {
          args.foreach(s => println(s))
        }
    
        echo("1", "2", "3")
        val arr = Array("What's", "up", "doc?")
        echo(arr: _*) // 奇奇怪怪的语法
    
        // 命名参数:使用命名参数允许你使用任意顺序传入参数
        def speed(distance: Float, time: Float): Float = distance * time
    
        println(speed(10, 20))
        println(speed(time = 10, distance = 20))
    
        // 缺省参数值:Scala 在定义函数时,允许指定参数的缺省值,从而允许在调用函数时不指明该参数,此时该参数使用缺省值。缺省参数通常配合命名参数使用
        def printTime(out: java.io.PrintStream = Console.out, divisor: Int = 1) = out.println("time = " + System.currentTimeMillis() / divisor)
    
        printTime()
        printTime(divisor = 666)
      }
    
      /**
        * 尾递归:在最后一行调用自身的递归
        * 理论上来说,使用递归的性能不如使用循环
        * 但是 scala 的编译器会针对尾递归进行优化(优化为循环)
        */
      def test_6(): Unit = {
        def test(i: Int): Unit = {
          if (i > 100) {
            println("OVER")
            throw new Exception("boom!") // 用来显示调用栈
          } else {
            test(i + 1) // 只要最后一行不是调用自身,就不构成尾递归
          }
          // i + 1
        }
    
        test(0)
      }
    
      // 减低代码重复
      def test_7(): Unit = {
    
        // 函数可以作为参数传递(可以用来简化一些逻辑基本相似的代码)
        def check(s1: String, s2: String,
                  checker: (String, String) => Boolean): Boolean = { // 该函数的类型为 (String,String ) =>Boolean,可以匹配任意使用两个 String 类型参数,返回值类型为 Boolean 的函数。
          checker(s1, s2)
        }
    
        def test(s1: String, s2: String): Boolean = {
          false
        }
    
        println(check("aaa", "aaa", _.equals(_)))
        println(check("aaa", "aaa", test(_, _)))
      }
    
      // 柯里化函数(没什么卵用):柯里化是把接受多个参数的函数变换成接受一个单一参数的函数
      def test_8(): Unit = {
        def test(i1: Int)(i2: Int)(i3: Int): Int = {
          i1 + i2 + i3
        }
    
        println(test(1)(2)(3))
      }
    
      // 创建新的控制结构:根据 scala 的高级函数特性,可以实现一些语法比较固定的控制结构
      def test_9(): Unit = {
        // 自定义控制结构
        def withPrintWriter(file: File, op: PrintWriter => Unit) {
          val writer = new PrintWriter(file)
          try {
            op(writer)
          } finally {
            writer.close()
          }
        }
    
        // 使用
        withPrintWriter(
          new File("date.txt"),
          writer => writer.println(new java.util.Date)
        )
      }
    
      // 传名参数
      def test_10(): Unit = {
        val assertionsEnabled = true
    
        // 传值参数
        def myAssert(predicate: () => Boolean) =
          if (assertionsEnabled && !predicate())
            throw new AssertionError
    
        // 传名参数
        def myNameAssert(predicate: => Boolean) =
          if (assertionsEnabled && !predicate)
            throw new AssertionError
    
        // 区别:传值参数是先计算后传值,传名参数相反
        myAssert(() => {
          // do something
          false
        })
        myNameAssert({
          // do something
          false
        })
      }
    }
    
  • 相关阅读:
    SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSAS 系列
    微软BI 之SSRS 系列
    微软BI 之SSRS 系列
    配置 SQL Server Email 发送以及 Job 的 Notification通知功能
  • 原文地址:https://www.cnblogs.com/CSunShine/p/11972919.html
Copyright © 2011-2022 走看看