zoukankan      html  css  js  c++  java
  • scala 学习笔记(07) 一等公民的函数

    在scala中一切皆对象,一切皆函数,函数跟Int,String、Class等其它类型是处于同等的地位,换句话说,使用函数跟使用普通的类型一样,没什么区别,因此:

    1、函数可以赋值给变量,可以当参数传递

      def helloWorld(msg: String): Unit = {
        println("Hello," + msg)
      }
    
      def foo = {
        println("foo")
      }
    
      def main(args: Array[String]) {
        //函数赋值给变量
        var d = helloWorld _
        d("jimmy") //Hello,jimmy
        //直接定义匿名函数
        d = (msg: String) => println("你好," + msg)
        d("杨俊明") //你好,杨俊明
    
        //无参函数,作为另一个函数的参数
        var x = (a: Unit, b: String) => {
          a
          println(b)
        }
    
        x(foo,"ha ha")
        //foo
        //haha
      }
    

    上面这些代码都是合法的

    2、函数可以嵌套

    既然class里可以定义class,函数是一等公民,理应享受跟class同样的待遇,因此当然也可以嵌套

      def funA(arr: Array[String]) = {
        def funB(a: String) = {
          '[' + a.trim + ']'
        }
        arr.foreach(x => println(funB(x)))
      }
    
      def main(args: Array[String]) {
        funA(Array("a", " b ", "c ", " f"))
        //  [a]
        //  [b]
        //  [c]
        //  [f]
      }
    

    3、所谓的偏函数

      def add(a: Int, b: Int, c: Int) = {
        a + b + c
      }
    
      def main(args: Array[String]) {
        val add2 = add(_: Int, _: Int, 0)
        println(add2(1, 2)) //3
      }
    

    利用这个技巧,可以实现带缺省参数,参数个数不同的"重载"版本

    4、闭包

      def fun = {
        var i = 10;
        def funTest = {
          println(i)
          i = i + 1
        }
        funTest
        println(i)
      }
    
      def main(args: Array[String]) {
        fun
      }
    

    funTest访问了funTest定义范围之外的变量 i

    5、高阶函数

      def main(args: Array[String]) {
    
        (1 to(9, 2)).map("*" *).foreach(x => println(" " * ((9 - x.length) / 2) + x))
    
    //        *
    //       ***
    //      *****
    //     *******
    //    *********
        
      }
    

     打印一颗小树冠,代码如此简单? 算法逻辑见下图,这不是重点,重点是上面这行代码是函数叠函数,to是对象1的一个函数,1 to (9,2),即从1到9,每次递增2,最终即为1,3,5,7,9,然后用map函数映射成一行行星号,然后再用foreach函数,结合前置空格输出

    // move         len
    // 4 * 1
    // 3 *** 3
    // 2 ***** 5
    // 1 ******* 7
    // 0********* 9


    
    

    6、克里化(curring)

      def add_1(a: Int, b: Int, c: Int) = {
        a + b + c
      }
    
      def add_2(a: Int) = (b: Int, c: Int) => {
        a + b + c
      }
    
      def add_3(a: Int) = (b: Int) => (c: Int) => {
        a + b + c
      }
    
      def main(args: Array[String]) {
        println(add_1(1, 2, 3)) //6
        println(add_2(1)(2, 3)) //6
        println(add_3(1)(2)(3)) //6
      }
    

    这个一直没明白真正的用途,号称是可以用来做参数的类型智能推断,但我感觉只是可以把参数拆散,在参数的调用方式上,略有『链式』编程的风格

    7、参数隐式转换

      def add(a: Int, b: Int) = a + b
    
      def foo(a:Int)={
        println(a)
      }
    
      def boo(a:String)={
        println(a)
      }
    
      implicit def convert(x: String): Int = {
        x match {
          case "one" => 1
          case "two" => 2
          case "three" => 3
          case _ => 0
        }
      }
    
      def main(args: Array[String]) {
        println(add("one", "two"))//3
        foo("one")//1
        boo("one")//one
      }
    

    我们并没有定义一个形如add(a:String,b:String)的加法函数,但是最终即成功调用了add("one","two"),秘密在于implicit做了参数的隐式转换,这一个很强大的武器,威力过于巨大,上面的这个转换,会把当前代码作用域的所有String参数,默认都按这个规则转换,foo("one")输出1就是证明,所以没掌握精通前,建议小心使用。

  • 相关阅读:
    shell脚本学习001
    Discuz 代码分析 001 forum.php
    Oauth2.0 入门
    第一篇文章
    position的四个属性值: relative ,absolute ,fixed,static
    JQuery中stop([clearQueue],[goToEnd])介绍
    <meta>
    sublime 2中Package control安装和使用
    ios 状态码
    <video>和<audio>标签,对视频和音频的支持
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/4771896.html
Copyright © 2011-2022 走看看