Scala 什么';“()=>;”之间的区别是什么还有“=>;”?

Scala 什么';“()=>;”之间的区别是什么还有“=>;”?,scala,Scala,假设我写了一个接受函数的方法,还有另一个返回函数的函数。我可以这样写我的方法: def logParens(f:()=>String)=println(f()) 或者像这样: def logNoParens(f: => String) = println(f) 假设我有一个返回字符串的方法 def foo = "foo" 为什么我可以将foo直接传递到logNoParens,而不是logParens?似乎Scala将foo强制为=>foo,然后将其传递到logNoParens log

假设我写了一个接受函数的方法,还有另一个返回函数的函数。我可以这样写我的方法:

def logParens(f:()=>String)=println(f())
或者像这样:

def logNoParens(f: => String) = println(f)
假设我有一个返回字符串的方法

def foo = "foo"
为什么我可以将foo直接传递到
logNoParens
,而不是
logParens
?似乎Scala将
foo
强制为
=>foo
,然后将其传递到
logNoParens

logParens(foo) // this gives me a type error
logParens(() => foo) // this compiles
logNoParens(foo) // this compiles just fine
=>
()=>
之间有什么区别?

简而言之:
()⇒ 字符串
创建类型为
单元的函数⇒ 字符串
while
⇒ 字符串
表示惰性类型
字符串
的值作为参数传递,因此如果引用该值,以后不会在函数体中重新计算该值

因此,当执行到达代码中的引用时,它将被计算一次,而当作为参数传递时,不会被计算

这种形式在创建接受某人的高阶函数时非常常见,例如:

def func(f: ⇒ String) : Either[Exception, String]{
   if (someCondition) {
     Right(f)
   } else {
     Left(new IllegalArgumentException("F can't be evaluated")
   }
}
可能的用法是:

def doF() {
  func {
    io.Stream.fromFile("path/to/file")
   }
}
def doF() {
 func {
   case _ ⇒ io.Stream.fromFile("path/to/file")
  }
}
当然,您可以将其重写如下:

def func(f: () ⇒ String) : Either[Exception, String]{
  if (someCondition) {
     Right(f())
  } else {
     Left(new IllegalArgumentException("F can't be evaluated")
  }
}
可能的用法是:

def doF() {
  func {
    io.Stream.fromFile("path/to/file")
   }
}
def doF() {
 func {
   case _ ⇒ io.Stream.fromFile("path/to/file")
  }
}

根据上下文,您可以选择前一种形式或后一种形式,这些形式在上述情况下完全可以互换。唯一的区别是,如果将惰性值传递给函数,它将只计算一次,但是,如果您将函数引用传递给函数-函数将执行并且计算结果将传递给函数的次数与函数中使用的次数相同。

正如雄心勃勃的用户所引用的那样,将参数添加到
def foo()
以获得eta扩展。谢谢,@som snytt。这类问题对谷歌来说很难回答。我还没有尝试过,但信息页面上说要搜索Stack Overflow中的Scala符号,如“=>”,可以使用symbolhound搜索。似乎每次在函数体中引用时都会对其进行计算<代码>定义日志(x:=>Int)=1到3 foreach{{u=>println(x)};var z=0;log{z=z+1;z}此示例记录1、2、3