=> Unit 与 () =>Unit的区别

messi_18 2011-06-10
def test(code: => Unit){ code }

与:
def test1(code: () => Unit){ code }


的区别。

其实,我更想知道第一个函数中参数的类型 => Unit是什么类型。
jilen 2011-06-10
第一个就是(没有参数列表)=>Unit,但是省略了空的参数列表,写的时候只能这样 test{
  println("hello")
}
第二个是(空的参数列表)=>Unit就只能 test{
()=> println("hello")
}

test分别要这样定义
def test(func :=> Unit){
func
}

def test(func: () => Unit){
func()
}
dogstar 2011-06-10
() => Unit ---> 是一个函数;
=> Unit ---> 是一个执行结果为Unit的表达式
jilen 2011-06-10
dogstar 写道
() => Unit ---> 是一个函数;
=> Unit ---> 是一个执行结果为Unit的表达式

有道理,恍然大悟的感觉
ordinary 2011-06-11
jilen 写道
第一个就是(没有参数列表)=>Unit,但是省略了空的参数列表,写的时候只能这样 test{
  println("hello")
}
第二个是(空的参数列表)=>Unit就只能 test{
()=> println("hello")
}

test分别要这样定义
def test(func :=> Unit){
func
}

def test(func: () => Unit){
func()
}



这个说法有问题吧!
两个都可调用func和func()
messi_18 2011-06-14
这几天,我已经搞明白了。code: => Unit是 by name 传递参数。参数是一个返回值为Unit的代码块。在传递的时候,参数没有被调用。比如:
def test(code : => Unit){
  println("start")
  code // 这行才会调用传入的代码块,写成code()亦可
  println("end")
}
test{// 此处的代码块不会马上被调用
  println("when evaluated")
  println("bb") 
}

结果:
start
when evaluated
bb
end

注意:when evaluated被打印在了start 和end中间。


而code: ()=>Unit参数的类型,是一个没有参数而且返回值为Unit的函数类型。
def test1(code: ()=>Unit){
  println("start")
  code() // 要想调用传入的代码块,必须写成code(),否则不会调用。
  println("end")
}
test1 {//此代码块,传入后立即执行。
println("when evaluated")
()=>{println("bb")}
}

结果:
when evaluated
start
bb
end

注意:when evaluated被打印在了start之前。
sirxenofex 2011-06-22
messi_18 写道
这几天,我已经搞明白了。code: => Unit是 by name 传递参数。参数是一个返回值为Unit的代码块。在传递的时候,参数没有被调用。比如:
def test(code : => Unit){
  println("start")
  code // 这行才会调用传入的代码块,写成code()亦可
  println("end")
}
test{// 此处的代码块不会马上被调用
  println("when evaluated")
  println("bb") 
}

结果:
start
when evaluated
bb
end

注意:when evaluated被打印在了start 和end中间。


而code: ()=>Unit参数的类型,是一个没有参数而且返回值为Unit的函数类型。
def test1(code: ()=>Unit){
  println("start")
  code() // 要想调用传入的代码块,必须写成code(),否则不会调用。
  println("end")
}
test1 {//此代码块,传入后立即执行。
println("when evaluated")
()=>{println("bb")}
}

结果:
when evaluated
start
bb
end

注意:when evaluated被打印在了start之前。


Scala没有什么代码块的概念。这个例子我也看了半天,实际上,在第二例当中,test1的参数是一个表达式。在Scala中,如果将要传入的参数正好是一个,则可以用花括号。这时候test1的参数列表是一个表达式,而这个表达式的结果是最后一行的返回,也就是一个函数() => { println("bb") },它被传给了test1的唯一参数。然后test1方法体执行。至于为什么when evaluated在另外三行之前,是因为它是在传参的时候,求表达式值的副产物。
其实code :=> Unit就是code : () => Unit,只是第一种是按名传参,用花括号可以把花括号内的所有东西作为一个函数传给code;第二种就是普通传参,但是它刚好只有一个参数。这时候用了花括号,就是花括号内表达式的值传进去了
kevinming 2011-07-15
专研精神可敬,copy上面童鞋的代码:
object FunctionTest2 extends App {

  def test(code: => Unit) {
    println("start")
    code // 这行才会调用传入的代码块,写成code()亦可  
    println("end")
  }
  test { // 此处的代码块不会马上被调用  
    println("when evaluated")
    println("bb")
  }

  def test1(code: () => Unit) {
    println("start")
    code() // 要想调用传入的代码块,必须写成code(),否则不会调用。  
    println("end")
  }
  test1 { //此代码块,传入后立即执行。  
    println("when evaluated")
    () => { println("bb") }
  }
}


看看反编译的东西:
  public void test(Function0<BoxedUnit> code)
  {
    Predef..MODULE$.println("start");
    code.apply$mcV$sp();
    Predef..MODULE$.println("end");
  }

  public void test1(Function0<BoxedUnit> code)
  {
    Predef..MODULE$.println("start");
    code.apply$mcV$sp();
    Predef..MODULE$.println("end");
  }

两个都是编译成Function0,但是看看下面主函数的反编译,test1的的when evaluated被编译到次处,然后才调用test1
  public final Object apply()
  {
    this.$outer.test(new FunctionTest2..anonfun.1());

    Predef..MODULE$.println("when evaluated");

    this.$outer.test1(
      new FunctionTest2..anonfun.2());

    return BoxedUnit.UNIT;
  }

下面是test{}块反编译:
public final class FunctionTest2$$anonfun$1 extends AbstractFunction0.mcV.sp
  implements Serializable
{
  public static final long serialVersionUID = 0L;

  public final void apply()
  {
    apply$mcV$sp(); } 
  public void apply$mcV$sp() { Predef..MODULE$.println("when evaluated");
    Predef..MODULE$.println("bb");
  }
}

下面是test1{}块反编译:
public final class FunctionTest2$$anonfun$2 extends AbstractFunction0.mcV.sp
  implements Serializable
{
  public static final long serialVersionUID = 0L;

  public final void apply()
  {
    apply$mcV$sp(); } 
  public void apply$mcV$sp() { Predef..MODULE$.println("bb");
  }
}


这里说明了传名参数=>和零参数函数()=>的区别了,后者是参数函数先计算运行了返回()=>实例在传给test1的,porgarmming in scala专门有一章节讲述byName Paramter
nielinjie 2011-11-16

楼上的两位讨论建立在两个不等价的代码块,如果要讨论=>Unit 和 ()=>Unit 的区别,代码应该如下。
object FunctionTest2 {
  def main(args: Array[String]) {
    def test(code: => Unit) {
      println("start")
      code 
      println("end")
    }
    test { 
      println("when evaluated")
      println("bb")
    }

    def test1(code: () => Unit) {
      println("start")
      code()  
      println("end")
    }
    test1 { 
      () =>
      println("when evaluated")
      println("bb")
    }
  }
}
Global site tag (gtag.js) - Google Analytics