【发布时间】:2014-08-20 15:50:12
【问题描述】:
在 scala 中,有一些按名称调用的参数:
def hello(who: => String) = println("hello, " + who)
参数who的类型是什么?
它将scala REPL上的函数显示为:
hello: (who: => String)Unit
类型还是=> String吗?它有什么名字吗?或者一些描述类型的文档?
answer 提出的其他问题
问题 1
(阅读§3.3.1(MethodTypes)的规范时)
方法类型是方法的类型,比如说我定义了一个方法hello:
def hello: String = "abc"
它的类型可以写成:=> String,对吧?虽然你可以看到 REPL 的响应是:
scala> def hello:String = "abc"
hello: String
如果我定义一个有参数的方法:
def goodname(name: String): String = name + "!"
方法的类型是什么?它应该类似于String => String,但不是。因为是方法类型,而String => String是函数类型。
问题 2
(阅读§3.3.1(MethodTypes)的规范时)
我可以这样理解:
def goodname(name: String): String = name + "!"
def print(f: String => String) = println(f("abc"))
print(goodname)
当我调用print(goodname)时,goodname的类型会转换为函数类型String => String,对吧?
但是对于无参数方法:
def hello: String = "abc"
可以转换什么函数类型?我试过了:
def print(f: () => String) = println(f())
但这不能编译:
print(hello)
错误是:
错误:类型不匹配; 发现:字符串 必需:() => 字符串
你能给我一个有效的例子吗?
问题 3
(在阅读 §6.26.2 (MethodConversions) 的规范时)
这种求值转换仅在类型未应用于参数时发生。所以,对于代码:
def myname:String = "abc"
def print(name: => String) = println(name)
print(myname)
我的问题是,当我打电话给print(myname) 时,是否发生了转换(我的意思是Evaluation conversion)?我猜,因为myname的类型只是=> String,所以可以直接传给print。
如果print 方法发生了变化:
def myname:String = "abc"
def print(name: String) = println(name)
print(myname)
这里Evaluation conversion肯定发生了,对吧?(从=> String到String)
【问题讨论】:
-
类型好像不是
()=>String,因为hello(() => "Freewind")无法编译 -
在您的示例中,
myname的类型是什么? -
@SeanVieira,修复和改进
-
RE:问题 1 - 方法不是值(第 3.3 节),因此它们本身没有类型。通过将对它们的调用包装在
FunctionN中,它们被转换 为值,其中apply方法调用底层方法。因此,当您将goodname传递给print时,您将Function1[String, String]的一个实例传递给print,它调用goodname:print(new Function1[String, String] { def apply(v: String) = goodname(v) }) -
RE:问题 2 - 无参数方法将转换为
Function0[T]。将hello传递给print时遇到问题的原因是编译器调用hello(因为此类方法“在每次引用无参数方法名称时都会重新评估 ”)。您必须明确告诉编译器使用_推迟评估;print(hello _)而不是print(hello)。
标签: scala callbyname