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)
  }
}
相关推荐
旋风小飞棍2 天前
如何在sheel中运行spark
大数据·开发语言·scala
rylshe13142 天前
在scala中sparkSQL连接mysql并添加新数据
开发语言·mysql·scala
MZWeiei4 天前
Spark任务调度流程详解
大数据·分布式·spark·scala
бесплатно4 天前
Scala流程控制
开发语言·后端·scala
Bin Watson11 天前
解决 Builroot 系统编译 perl 编译报错问题
开发语言·scala·perl
什么芮.14 天前
大数据应用开发和项目实战(2)
大数据·pytorch·sql·spark·scala
不要天天开心16 天前
Spark-Streaming核心编程:有状态转化操作与DStream输出
scala
欧先生^_^17 天前
Scala语法基础
开发语言·后端·scala
不要天天开心19 天前
大数据利器:Kafka与Spark的深度探索
spark·scala
不要天天开心19 天前
Kafka与Spark-Streaming:大数据处理的黄金搭档
kafka·scala