问题描述
在scala中,有一些按名字呼叫的参数:
In scala, there is some call-by-name parameters:
def hello(who: => String) = println("hello, " + who)
参数who
的类型是什么?
它将scala REPL上的功能显示为:
It shows the function on scala REPL as:
hello: (who: => String)Unit
类型是否仍为=> String
?有什么名字吗?还是一些描述类型的文档?
Is the type still => String
? Is there any name for it? Or some documentation to describe the type?
(阅读第3.3.1节(MethodTypes)的规范时)
(When reading the spec of §3.3.1 (MethodTypes))
方法类型是方法的类型,例如我定义了方法hello
:
Method type is the type of a method, say I defined a method hello
:
def hello: String = "abc"
它的类型可以写为:=> String
,对吗?尽管您可以看到REPL响应是:
The type of the it can be written as: => String
, right? Although you can see the REPL response is:
scala> def hello:String = "abc"
hello: String
如果我定义了一个带有参数的方法:
If I define a method which has parameters:
def goodname(name: String): String = name + "!"
该方法的类型是什么?它应该与String => String
类似,但不相似.因为它是方法类型,而String => String
是函数类型.
What's the type of the method? It should be similar to String => String
, but not. Because it's a method type, and String => String
is a function type.
(阅读第3.3.1节(MethodTypes)的规范时)
(When reading the spec of §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
,对吧?
When I call print(goodname)
, the type of goodname
will be converted to the function type String => String
, right?
但是对于无参数方法:
def hello: String = "abc"
可以转换什么功能类型?我试过了:
What function type can it be converted? I tried:
def print(f: () => String) = println(f())
但是无法编译:
print(hello)
错误是:
您能给我一个可行的例子吗?
Could you give me an example that works?
(阅读第6.26.2节(MethodConversions)的规范时)
(When reading the spec of §6.26.2 (MethodConversions))
仅当类型不应用于自变量时,才会发生此 Evaluation 转换.因此,对于代码:
This Evaluation conversion is only happened when the type is not applied to argument. So, for code:
def myname:String = "abc"
def print(name: => String) = println(name)
print(myname)
我的问题是,当我呼叫print(myname)
时,是否发生了转换(我的意思是Evaluation conversion
)?我猜想,由于myname
的类型仅为=> String
,因此可以将其直接传递给print
.
My question is, when I call print(myname)
, is there conversion(I mean Evaluation conversion
) happened? I guess, since the type of myname
is just => String
, so it can be passed to print
directly.
如果print
方法已更改:
def myname:String = "abc"
def print(name: String) = println(name)
print(myname)
Evaluation conversion
肯定发生了,对吗?(从=> String
到String
)
Here the Evaluation conversion
is definitely happened, right?(From => String
to String
)
推荐答案
因此,按名称调用参数的类型是(大约)() => T
(或者,如果愿意,可以是Function0[T]
).如果:javap
接受按名字调用参数的方法,您将看到编译后的代码接受scala.Function0<java.lang.Object>
类型的参数.
So the type of a call-by-name param is (approximately) () => T
(or Function0[T]
if you prefer). If you :javap
a method that accepts a call-by-name parameter you will see that the compiled code accepts a param of the type 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)
;为什么不编译? (提示,请考虑在呼叫站点进行扩展). (将鼠标悬停在以下空白处可以查看答案):
Doubts surrounding the approximation
You may be tempted to try passing a () => T
to your method. Try callByName(() => 12)
; why does it not compile? (Hint, consider the expansion at the call site). (Hover on the following blank to see the answer):
=> T
实际是什么
=> T
实际上是方法类型,而不是对象.因此,之前发生的所有事情都是编译器所做工作的近似值,并且可以随时更改.引用自§3.3 :
What => T
actually is
=> T
is actually a method type, not an object. So everything that goes before is an approximation of what the compiler does and can change at any time. Quoting from §3.3:
那么方法类型是什么?引用自§3.3.1(方法类型):
So what are method types? Quoting from §3.3.1 (MethodTypes):
方法类型不作为值类型存在.如果将方法名称用作值,则其类型将隐式转换为相应的函数类型(§6.26).
Method types do not exist as types of values. If a method name is used as a value, its type is implicitly converted to a corresponding function type (§6.26).
和§6.26.3(MethodConversions )状态:
评估.类型为=> T
的无参数方法m
总是通过评估绑定到m
的表达式而转换为类型T
.
Evaluation. A parameterless method m
of type => T
is always converted to type T
by evaluating the expression to which m
is bound.
所以类型=> T
的正确翻译总是:
So the proper translation of the type => T
is always:
def random$name$here: T
示例
这是一个可以玩的示例类:
Example
Here's an example class to play around with:
class TestParamless {
def paramless: Int = 1
def callByName(f: => Int) = f
def example: Int = callByName(paramless)
}
尝试new TestParamless().example
,也尝试:javap TestParamless
(在scala REPL中).
Try new TestParamless().example
and also, :javap TestParamless
(in the scala REPL).
这篇关于`=>的类型是什么?在Scala中使用String`吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!