什么';s是`=>;scala中的字符串?

什么';s是`=>;scala中的字符串?,scala,callbyname,Scala,Callbyname,在scala中,有一些按名称调用参数: def hello(who: => String) = println("hello, " + who) def goodname(name: String): String = name + "!" 参数的类型是什么who 它将scala REPL上的函数显示为: hello: (who: => String)Unit 类型仍然是字符串吗?有名字吗?或者一些文档来描述类型 秘书长提出的进一步问题 问题1 (阅读§3.3.1(方法类型)的

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

def hello(who: => String) = println("hello, " + who)
def goodname(name: String): String = name + "!"
参数的类型是什么
who

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

hello: (who: => String)Unit
类型仍然是字符串吗?有名字吗?或者一些文档来描述类型

秘书长提出的进一步问题 问题1 (阅读§3.3.1(方法类型)的规范时)

方法类型是方法的类型,比如我定义了一个方法
hello

def hello: String = "abc"
它的类型可以写为:
=>String
,对吗?尽管您可以看到REPL响应是:

scala> def hello:String = "abc"
hello: String
如果我定义了一个具有参数的方法:

def hello(who: => String) = println("hello, " + who)
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
,对吗

但对于无参数方法:

def hello: String = "abc"
可以转换什么函数类型?我试过:

def print(f: () => String) = println(f())
但这是无法编译的:

print(hello)
错误是:

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

你能给我举个有效的例子吗

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

求值转换仅在类型未应用于参数时发生。因此,对于代码:

def myname:String = "abc"
def print(name: => String) = println(name)
print(myname)
我的问题是,当我调用
print(myname)
时,是否发生了转换(我的意思是
评估转换
)?我猜,由于
myname
的类型只是
=>String
,因此它可以直接传递到
print

如果
打印方法已更改:

def myname:String = "abc"
def print(name: String) = println(name)
print(myname)
这里肯定发生了
求值转换
,对吗?(从
=>String
String

引用自:

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

因此,按名称参数调用的类型(大约)是
()=>T
(或者
Function0[T]
,如果您愿意的话)。如果您
:javap
一个接受按名称参数调用的方法,您将看到编译后的代码接受类型为
scala.Function0
的参数

近似的一个例子 翻译如下:

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(新函数0[()=>Int]{ def apply()=()=>12 }) 也就是说,不是传入一个返回
Int
Function0
,而是传入一个返回
Int
Function0

T实际上是什么
=>T
实际上是一种方法类型,而不是对象。因此,前面的所有内容都是编译器所做工作的近似值,并且可以随时更改。引述自:

下面解释的类型不表示值集,也不在程序中显式显示。它们在本报告中作为已定义标识符的内部类型引入

那么什么是方法类型呢?引述自:

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

方法类型不作为值类型存在。如果方法名用作值,则其类型将隐式转换为相应的函数类型()

并指出:

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

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

因此,类型
=>T
的正确翻译始终是:

def random$name$here: T
例子 下面是一个示例类:

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

请尝试
newtestparamless()。例如
,还有,
:javap TestParamless
(在scala REPL中)。

@Freewind,是的,它是。Ok。我想跟进此事。如果两者都是
Function0
,那么为什么这两种情况的语法都不同呢
def callByName[T](f:()=>T)=f()
f
之后需要
()
,而且
callByName{1+1}
将给出语法错误。你需要
()=>1+1
。为什么
你好(()=>“Freewind”)
无法编译?似乎
=>String
的类型不同于
()=>String
()=>T
是一个从单位到T的函数,而
=>T
是一个按名称调用的类型,在我看来,它们的类型不同。我添加了更多的细节-我稍后会尝试重新处理,以使其更清晰。似乎类型不是
()=>String
,因为在您的示例中无法编译
hello(()=>“Freewind”)
myname
的类型是什么?@SeanVieira,修复和改进了问题1-方法不是值(§3.3),因此它们没有这样的类型。通过在
function n
中包装对它们的调用,将它们转换为值,
apply
方法调用基础方法。因此,当您将
goodname
传递给
print
时,您正在将
Function1[String,String]
的一个实例传递给
print
,后者调用
goodname