scala 中 `=> String` 的类型是什么?

2024-04-08

在scala中,有一些按名称调用的参数:

def hello(who: => String) = println("hello, " + who)

参数的类型是什么who?

它将 scala REPL 上的函数显示为:

hello: (who: => String)Unit

类型还是=> String?它有什么名字吗?或者一些描述类型的文档?

提出的进一步问题answer https://stackoverflow.com/a/25409347/342235

问题1

(阅读§3.3.1(方法类型)的规范时)

方法类型是方法的类型,假设我定义了一个方法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(方法类型)的规范时)

我可以这样理解:

def goodname(name: String): String = name + "!"
def print(f: String => String) = println(f("abc"))
print(goodname)

当我打电话时print(goodname),类型goodname将被转换为函数类型String => String, right?

但对于无参数方法:

def hello: String = "abc"

可以转换什么函数类型?我试过:

def print(f: () => String) = println(f())

但这无法编译:

print(hello)

错误是:

错误:类型不匹配; 发现:字符串 必需:() => 字符串

你能给我一个有效的例子吗?

问题3

(阅读§6.26.2(方法转换)的规范时)

This 评估仅当类型未应用于参数时才会发生转换。所以,对于代码:

def myname:String = "abc"
def print(name: => String) = println(name)
print(myname)

我的问题是,当我打电话时print(myname),是否有转换(我的意思是Evaluation conversion)发生了?我想,由于类型myname只是=> String,因此可以传递给print直接地。

If the print方法已更改:

def myname:String = "abc"
def print(name: String) = println(name)
print(myname)

这里的Evaluation conversion肯定发生过,对吧?(来自=> String to String)


引用自规范第 4.6.1 条 http://scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html#by-name-parameters:

这样的参数的类型就是无参数方法类型=> T.

所以按名称调用参数的类型是(大约)() => T (or Function0[T]如果你更喜欢)。如果你:javap接受按名称调用参数的方法,您将看到编译后的代码接受类型的参数scala.Function0<java.lang.Object>.

近似的例子

翻译如下:

def callByName[T](f: => T) = f

callByName { /* magic */
    1 + 1
/* ends here */ }

实际上是:

def callByName[T](f: Function0[T]) = f.apply()

callByName(new Function0[Int] {
  def apply() = { /* magic */
    1 + 1
  /* ends here */ }
})

对近似值的质疑

您可能会想尝试通过() => T按照你的方法。尝试callByName(() => 12);为什么它不编译? (提示,考虑调用站点的扩展)。 (将鼠标悬停在以下空白处即可查看答案):

原因callByName(() => 12)无法编译是因为扩展被视为: callByName(new Function0[() => Int] { def apply() = () => 12 }) 也就是说,而不是传递一个Function0它返回一个Int你正在传递一个Function0它返回一个Function0它返回一个Int.

What => T实际上是

=> T实际上是方法类型,而不是对象。因此,之前的所有内容都是编译器所做的近似操作,并且可以随时更改。引用自§3.3 http://scala-lang.org/files/archive/spec/2.11/03-types.html#non-value-types:

下面解释的类型并不表示值的集合,它们也不明确地出现在程序中。它们在本报告中作为已定义标识符的内部类型进行介绍。

那么什么是方法类型呢?引用自§3.3.1(方法类型) http://scala-lang.org/files/archive/spec/2.11/03-types.html#method-types:

一种特殊情况是不带任何参数的方法类型。它们写在这里=> T。无参数方法名称表达式每次引用无参数方法名称时都会重新计算。

方法类型不作为值类型存在。如果方法名称用作值,则其类型会隐式转换为相应的函数类型(§6.26 http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#implicit-conversions).

And §6.26.3(方法转换) http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#method-conversions states:

以下四种隐式转换可应用于未应用于某些参数列表的方法。

评估。无参数方法m类型的=> T总是转换为类型T通过评估表达式m已绑定。

所以类型的正确翻译=> T总是:

def random$name$here: T

Example

这是一个可以使用的示例类:

class TestParamless {
  def paramless: Int = 1
  def callByName(f: => Int) = f
  def example: Int = callByName(paramless)
}

Try new TestParamless().example并且,:javap TestParamless(在 scala REPL 中)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scala 中 `=> String` 的类型是什么? 的相关文章

随机推荐