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
        })
      }
    }
    
  • 相关阅读:
    [Kali_Debian] 清除无用的库文件(清理系统,洁癖专用)-布布扣-bubuko.com
    给 Linux 系统“减肥”,系统垃圾清理_系统安装与配置管理_Linux Today
    命令行选项
    SQL 优化
    精通initramfs构建step by step
    常用正则表达式
    Chrome_浏览器开发人员工具
    按键精灵
    CMD命令大全
    50种折纸方法
  • 原文地址:https://www.cnblogs.com/CSunShine/p/11972919.html
Copyright © 2011-2022 走看看