Scala传名参数(By-Name)

Posted duanxz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala传名参数(By-Name)相关的知识,希望对你有一定的参考价值。

1.=>

在了解Scala的By-Name参数之前,先了解下“=>”在Scala中有几种用法:

1.对于值,“=>”相当于lambda表达式。如:

scala> List(1,2,3).map{(x: Int) => x*2}
res0: List[Int] = List(2, 4, 6)
2.对于类型,“=>”两端的类型(如,A => B、(A, B) => C等)。它对于Function<n>[A[, B...], T]是一个语法糖。一个函数传入参数是A[, B...],并且返回一个T类型的值。如:
scala> val test: Function1[Int,String] = myInt => "my int: " + myInt.toString
test: Int => String = <function1>
scala> test(1)
res0: String = my int: 1

scala> val test: Int => String = myInt => "my int: "+ myInt.toString
test: Int => String = <function1>

scala> test(1)
res1: String = my int: 1
  • 如果参数为空,即“=>”左边为空,形式是:() => T。如
    scala> val test: Function0[String] = () => "Hello"
    test: () => String = <function0>
     
    scala> test()
    res3: String = Hello
     
     
    scala> val test: () => String = () => "Hello"
    test: () => String = <function0>
     
    scala> test()
    res4: String = Hello

如果无返回值,即“=>”右边为空,形式是:A[, B...] => Unit

    1. scala> val test: Int => Unit = myInt => println(myInt)
    2. test: Int => Unit = <function1>
    3. scala> test(1)
    4. 1

  • 如果无参且无返回值,即“=>”两边都为空,形式是:() => Unit
    1. scala> val test: Function0[Unit] = () => println("Hello")
    2. test: () => Unit = <function0>
    3. scala> test()
    4. Hello
    5. scala> val test: () => Unit = () => println("Hello")
    6. test: () => Unit = <function0>
    7. scala> test()
    8. Hello
3.如果作为一个函数的参数的类型声明,且左边没有任何符号,如def func(param: => T)。这种形式叫做By-Name parameter。

4.在case语句中,“=>”用于分隔模式和结果表达式。
 

2.By-Name Parameter

By-Value参数,我们都比较熟悉,参数在进入函数前就进行计算,最后传入的最终的计算结果
By-Name参数,表示参数在进入函数后,每次在函数体内调用的时候才会计算。
def myByName1(param: () => Boolean): Unit = {
 
println("start")
 
println(param) //println(param.apply())也可以
 
println("end")
 
}
 
 
 
//要实现传名函数,要定义的类型开始于“=>”,而不是“() =>”。
 
//myByName1{7>9}不会有效,因为缺少“() =>”
 
myByName1{() =>
 
println("enter")
 
7 > 9
 
}

 

其中“=>”后面的代码是整体作为参数,所以会在函数体里被调用的时候才会执行。输出如下:
 
start
 
enter
 
false
 
end
再看下一种情况,只有“() =>”之后的代码是By-Name参数。“() =>”之前的代码是By-Value参数,即当调用myByName2的时候就会立即执行:
  1.  
    def myByName2(param: () => Boolean): Unit = {
  2.  
    println("start")
  3.  
    println(param) //println(param.apply())也可以
  4.  
    println("end")
  5.  
    }
  6.  
     
  7.  
    myByName2{
  8.  
    println("enter")
  9.  
    () => 7 > 9
  10.  
    }

输出如下:
  1.  
    enter
  2.  
    start
  3.  
    false
  4.  
    end

下面来看标准的By-Name参数: 
  1.  
    def myByName(param: => Boolean): Unit = {
  2.  
    println("start")
  3.  
    println(param)
  4.  
    println("end")
  5.  
    }
  6.  
     
  7.  
    myByName{
  8.  
    println("enter")
  9.  
    7 > 9}

3.函数作为参数

By-Name有点像把函数作为参数的意思,但是实际上却不是。这里看下把函数作为参数的形式:
    1.  
      def test(num: Int => String, str: String => Int): Unit = {
    2.  
      val i = 10
    3.  
      val s = "5"
    4.  
      println(num(i))
    5.  
      println(str(s))
    6.  
      }
    7.  
       
    8.  
      def num(x: Int): String = {
    9.  
      x.toString()
    10.  
      }
    11.  
       
    12.  
      def str(s: String): Int = {
    13.  
      s.toInt
    14.  
      }
    15.  
       
    16.  
      test(num, str)
    17.  

以上是关于Scala传名参数(By-Name)的主要内容,如果未能解决你的问题,请参考以下文章

29.scala传名参数

scala中的传名调用

匿名函数上的scala By-name参数

Scala中的参数

Scala函数的调用

控制抽象