scala05-函数式编程02

函数式编程-函数对象作为方法的参数

scala 复制代码
package com.zishi.scala.a02.okk05

/**
 * 将函数对象作为方法的参数来使用,
 * 函数本身就是对象,
 * 对象的使用领域:变量,方法参数,返回值类型
 *
 * 类比Java
 * public void test(User user) {
 * }
 *
 * User user = new User();
 *
 * test(user); 对象作为方法的参数
 * test(new User());
 */
object Test05_Lambda01 {

  def main(args: Array[String]): Unit = {

    // 创建方法对象
    def fun33(age: Int): String = {
      "Hello:" + age
    }

    /**
     *  等同于
     *  def test(f: Function1[Int, String]) : Unit = {}
     */
    def test(f: (Int) => String): Unit = {
      println(f(23))
    }

    val f2 = fun33 _
    test(f2) // Hello:23


    def sum(x:Int, y:Int): Int = {
      x + y
    }

    def sub(x: Int, y: Int): Int = {
      x - y
    }

    def test2(fun: (Int, Int) => Int): Unit = {
      val i = fun(10, 20)
      println(i)
    }

    // 将函数名称作为参数传递为一个函数作为参数,此时不需要下划线
    test2(sum)
    //TODO: 这里函数的名称sub真的很重要吗?
    // 类比Java:test(new User())
    test2(sub)

    // TODO: 将参数传递的名字取消掉
    // 如果函数声明没有def和名称,那么就是匿名函数
    test2((x: Int, y: Int) => {
      x * y
    })

    // 将匿名函数赋值给一个变量
    val a = (x: Int, y: Int) => {
      x / y
    }
    test2(a)

    // 匿名函数的简化原则
    //(1)参数的类型可以省略,会根据形参进行自动的推导
    test2((x, y) => {
      x * y
    })
    //(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。
    //(3)匿名函数如果只有一行,则大括号也可以省略
    test2((x, y) => x * y)
    //(4)如果参数只出现一次,并且按照顺序执行一次,则参数省略且后面参数可以用_代替
    println("-------------------")
    test2(_ * _) // 下划线类似占位符,第一个下划线代表第一个参数,依次类推
    //(5) 如果可以推断出,当前传入的println是一个函数体,而不是调用语句,可以直接省略下划线



    // 定义一个函数,以函数作为参数输入
    def f(func: String => Unit): Unit = {
      func("abcde")
    }

    f((name: String) => {
      println(name)
    })

    println("========================")

    // 匿名函数的简化原则
    //(1)参数的类型可以省略,会根据形参进行自动的推导
    f((name) => {
      println(name)
    })

    //(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。
    f(name => {
      println(name)
    })

    //(3)匿名函数如果只有一行,则大括号也可以省略
    f(name => println(name))

    //(4) 如果参数只出现一次,则参数省略且后面参数可以用_代替
    f(println(_))

    //(5) 如果可以推断出,当前传入的println是一个函数体,而不是调用语句,可以直接省略下划线
    f(println _)
    f(println)

  }
}

练习

scala 复制代码
package com.zishi.scala.a02.okk05

object Test05_Lambda02 {
  def main(args: Array[String]): Unit = {
    // 实际示例,定义一个"二元运算"函数,只操作1和2两个数,但是具体运算通过参数传入
    def dualFunctionOneAndTwo(fun: (Int, Int) => Int): Int = {
      fun(1, 2)
    }

    val add = (a: Int, b: Int) => a + b
    val minus = (a: Int, b: Int) => a - b

    println(dualFunctionOneAndTwo(add))
    println(dualFunctionOneAndTwo(minus))

    // 匿名函数简化
    println(dualFunctionOneAndTwo((a: Int, b: Int) => a + b))
    println(dualFunctionOneAndTwo((a: Int, b: Int) => a - b))

    println(dualFunctionOneAndTwo((a, b) => a + b))
    println(dualFunctionOneAndTwo(_ + _))
    println(dualFunctionOneAndTwo(_ - _))

    println(dualFunctionOneAndTwo((a, b) => b - a))
    println(dualFunctionOneAndTwo(-_ + _))

    // Java里面存在引用类型和基本类型同时作为方法的参数 void test(int x, User u);
    // 类比java
    def cal(x: Int, func: (Int, Int) => Int, y: Int) = {
      func(x, y)
    }

    def sum(x: Int, y: Int) = {
      x + y
    }

    println("....")
    println(cal(3,
      (x: Int, y: Int) => {
      x + y
    }, 5))

    println(cal(3, (x: Int, y: Int) => x + y, 5))
    println(cal(3, (x, y) => x + y, 5))
    println(cal(3, _ + _, 5))

  }
}

函数作为返回值

scala 复制代码
package com.zishi.scala.a02.okk05

/**
 * 函数作为返回值返回
 * 类比Java
 * public User test() {
 * User user = new User();
 * return user;
 * }
 *
 * public User test() {
 * return new User();
 * }
 */
object Test05_Lambda03 {
  def main(args: Array[String]): Unit = {
    // 函数作为返回值返回

    def outer() = {
      def inner(): Unit = {
        print("abc")
      }

      inner _
    }

    val f1 = outer()
    f1()

    //下面的调用更诡异
    outer()() // abc

    println("...............")
    def outer2() = {
      //def inner(name: String): Unit = print(s"abc${name}")
      def inner(name: String): Unit = print(s"abc${name}")
      inner _
    }

    val f2 = outer2()
    f2("aege") // abcabcaege


    def outer3(x: Int) = {
      def mid(f : (Int, Int) => Int) = {
        def inner(y: Int) = {
          f(x, y)
        }
        inner _
      }
      mid _
    }

    println()

    val mid = outer3(1)
    val inner = mid( _ + _)
    val res = inner(3)
    println(res)

    val res2 = outer3(1)( _ + _)(3)
    println(res2)
  }
}

高阶函数01

scala 复制代码
package com.zishi.scala.a02.okk05

object Test06_HighOrderFunction01 {
  def main(args: Array[String]): Unit = {
    def f(n: Int): Int = {
      println("f调用")
      n + 1
    }



    val result: Int = f(123)
    println(result) // 124

    // 1. 函数作为值进行传递
    val f1: Int => Int = f
    val f2 = f _

    println(f1) // com.zishi.scala.okk05.Test06_HighOrderFunction$$$Lambda$16/0x00000008000d7040@1e67a849
    println(f1(12)) // 13
    println(f2) // com.zishi.scala.okk05.Test06_HighOrderFunction$$$Lambda$17/0x00000008000d6840@57d5872c
    println(f2(35)) // 36


    def fun(): Int = {
      println("fun调用")
      1
    }
    val f3: () => Int = fun
    val f4 = fun _
    println(f3) // com.zishi.scala.okk05.Test06_HighOrderFunction$$$Lambda$18/0x00000008000d6040@64c87930
    println(f4) // com.zishi.scala.okk05.Test06_HighOrderFunction$$$Lambda$19/0x00000008000d6440@400cff1a
  }
}

高阶函数02

scala 复制代码
object Test06_HighOrderFunction02 {
  def main(args: Array[String]): Unit = {
    // 2. 函数作为参数进行传递
    // 定义二元计算函数
    def dualEval(op: (Int, Int) => Int, a: Int, b: Int): Int = {
      op(a, b)
    }

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

    println(dualEval(add, 12, 35))
    println(dualEval((a, b) => a + b, 12, 35))
    println(dualEval(_ + _, 12, 35))

    // 3. 函数作为函数的返回值返回
    def f5(): Int => Unit = {
      def f6(a: Int): Unit = {
        println("f6调用 " + a)
      }
      f6 // 将函数直接返回
    }

    //    val f6 = f5()
    //    println(f6)
    //    println(f6(25))

    println(f5()(25))
  }
}


object Test06_HighOrderFunction03 {
  def main(args: Array[String]): Unit = {
    // 3. 函数作为函数的返回值返回
    def f5(): Int => Unit = {
      def f6(a: Int): Unit = {
        println("f6调用 " + a)
      }
      f6 // 将函数直接返回
    }

    //    val f6 = f5()
    //    println(f6)
    //    println(f6(25))

    println(f5()(25))
  }
}

练习

scala 复制代码
package com.zishi.scala.a02.okk05

/**
 * 函数作为返回值
 */
object Test08_Practice {
  def main(args: Array[String]): Unit = {
    // 2. 练习2
    def func(i: Int): String => (Char => Boolean) = {
      def f1(s: String): Char => Boolean = {
        def f2(c: Char): Boolean = {
          if (i == 0 && s == "" && c == '0') false else true
        }
        f2
      }
      f1
    }

    println(func(0)("")('0'))//false
    println(func(0)("")('1'))//true
    println(func(23)("")('0'))//true
    println(func(0)("hello")('0'))//true

    // 匿名函数简写
    def func1(i: Int): String => (Char => Boolean) = {
      s => c => if (i == 0 && s == "" && c == '0') false else true
    }

    println(func1(0)("")('0'))//false
    println(func1(0)("")('1'))//true
    println(func1(23)("")('0'))//true
    println(func1(0)("hello")('0'))//true

    // 柯里化
    def func2(i: Int)(s: String)(c: Char): Boolean = {
      if (i == 0 && s == "" && c == '0') false else true
    }

    println(func2(0)("")('0'))//false
    println(func2(0)("")('1'))//true
    println(func2(23)("")('0'))//true
    println(func2(0)("hello")('0'))//true
  }
}

object Test08_Practice01 {
  def main(args: Array[String]): Unit = {
    // 1. 练习1
    val fun = (i: Int, s: String, c: Char) => {
      if (i == 0 && s == "" && c == '0') false else true
    }

    println(fun(0, "", '0'))//false
    println(fun(0, "", '1'))//true
    println(fun(23, "", '0'))//true
    println(fun(0, "hello", '0'))//true
  }
}
scala 复制代码
package com.zishi.scala.a02.okk05

/**
 * 函数作为返回值
 */
object Test08_Practice {
  def main(args: Array[String]): Unit = {
    // 2. 练习2 内层函数可以使用外层函数的参数

    // func 参数列表:i: Int, 返回值类型(函数类型):String => (Char => Boolean)
    def func(i: Int): String => (Char => Boolean) = {
      // f1函数: 参数列表:s: String, 返回值类型:Char => Boolean
      def f1(s: String): Char => Boolean = {
        // f2函数: 参数列表:c: Char, 返回值类型:Boolean
        def f2(c: Char): Boolean = {
          if (i == 0 && s == "" && c == '0') false else true
        }
        f2
      }
      f1
    }

    println(func(0)("")('0'))//false
    println(func(0)("")('1'))//true
    println(func(23)("")('0'))//true
    println(func(0)("hello")('0'))//true


    def func33(i: Int): String => (Char => Boolean) = {
      // f1函数: 参数列表:s: String, 返回值类型:Char => Boolean
      def f1(s: String): Char => Boolean = {
        // f2函数: 参数列表:c: Char, 返回值类型:Boolean
         // def f2(c: Char): Boolean = if (i == 0 && s == "" && c == '0') false else true
         //def f2(c: Char) = if (i == 0 && s == "" && c == '0') false else true
         // val f2 = (c: Char) => if (i == 0 && s == "" && c == '0') false else true
         // c => if (i == 0 && s == "" && c == '0') false else true
        c => true
      }
      f1
    }

    def func44(i: Int): String => (Char => Boolean) = {
      // f1函数: 参数列表:s: String, 返回值类型:Char => Boolean
      //def f1(s: String): Char => Boolean = c => if (i == 0 && s == "" && c == '0') false else true
      //def f1(s: String) = (c:Char) => if (i == 0 && s == "" && c == '0') false else true
      //val f1 = (s: String) => (c:Char) => if (i == 0 && s == "" && c == '0') false else true
      //(s: String) => (c:Char) => if (i == 0 && s == "" && c == '0') false else true
      s => c => if (i == 0 && s == "" && c == '0') false else true
    }
    
    // 匿名函数简写
    def func1(i: Int): String => (Char => Boolean) = {
      s => c => if (i == 0 && s == "" && c == '0') false else true
    }

    println(func1(0)("")('0'))//false
    println(func1(0)("")('1'))//true
    println(func1(23)("")('0'))//true
    println(func1(0)("hello")('0'))//true

    // 柯里化
    def func2(i: Int)(s: String)(c: Char): Boolean = {
      if (i == 0 && s == "" && c == '0') false else true
    }

    println(func2(0)("")('0'))//false
    println(func2(0)("")('1'))//true
    println(func2(23)("")('0'))//true
    println(func2(0)("hello")('0'))//true
  }
}
  • 简化代码约定
scala 复制代码
package com.zishi.scala.a02.okk05

/**
 * 函数至简原则注意事项
 */
object Test08_Practice02 {
  def main(args: Array[String]): Unit = {

    def test(name: String, f: String => Unit): Unit = {
      f(name)
    }

    def func(name: String): Unit = {
      println("name:" + name)
    }

    // 1. 调用
    test("zbc", func)

    // 2. 化简
    test("zbc", (name: String) => println("name:" + name))

    //3, 化简
    test("zbc", name => println("name:" + name))

    //4, 下面的化简不对
    // _ 代表第二个参数,第二个参数是函数对象,并不是函数对象的参数
    test("zbc", _ => println("name:" + _)) //输出结果为:com.zishi.scala.a02.okk05.Test08_Practice02$$$Lambda$18/0x000000080009d840@2ea6137

    // 报错:type mismatch, 返回的是Unit
    // 这是因为这里使用的函数的嵌套。不确定下划线 _ 是哪层函数的简化
    // test("zbc",println("name:" + _))

    // 做个如下变形


    def test2(f: String => Unit): Unit = {
      f("测试变形")
    }

    def func2(name: String): Unit = {
      println("func2:" + name)
    }
    // 1. 化简
    test2((name: String) => println("func2:" + name))

    // 2. 化简
    test2(name => println("func2:" + name))

    //3. 简化
    test2(name => println(name))
    test2(println(_))
    test2(println _)
    test2(println)
  }
}
相关推荐
今天我又学废了7 小时前
scala学习记录,Set,Map
开发语言·学习·scala
富能量爆棚2 天前
scala的属性访问权限
scala
富能量爆棚2 天前
Scala的包及其导入
开发语言·后端·scala
睎zyl2 天前
Scala的访问权限。
开发语言·后端·scala
富能量爆棚3 天前
Scala的属性访问权限(一)默认访问权限
开发语言·后端·scala
富能量爆棚3 天前
scala的控制方法作用域
scala
2401_871290583 天前
Scala 的例题:银行账户钱存取功能
scala
白总Server5 天前
Ribbon解说
后端·spring cloud·微服务·云原生·ribbon·架构·scala
白总Server6 天前
Ribbon的轮询策略实现方法
开发语言·后端·spring cloud·ribbon·架构·scala·1024程序员节
anqi276 天前
Scala 的trait
开发语言·后端·scala