`=>的类型是什么?在Scala中使用String`吗? [英] What's the type of `=> String` in scala?

查看:102
本文介绍了`=>的类型是什么?在Scala中使用String`吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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)

错误是:

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

error: type mismatch; found : String required: () => String

您能给我一个可行的例子吗?

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肯定发生了,对吗?(从=> StringString)

Here the Evaluation conversion is definitely happened, right?(From => String to String)

推荐答案

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

因此,按名称调用参数的类型是(大约)() => 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):

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

The reason callByName(() => 12) does not compile is because the expansion is treated as: callByName(new Function0[() => Int] { def apply() = () => 12 }) That is, rather than passing in a Function0 which returns an Int you are passing in a Function0 which returns a Function0 which returns an Int.

=> 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:

以下说明的类型不表示值集,也不在程序中明确显示.在本报告中将它们作为已定义标识符的内部类型进行介绍.

The types explained in the following do not denote sets of values, nor do they appear explicitly in programs. They are introduced in this report as the internal types of defined identifiers.

那么方法类型是什么?引用自§3.3.1(方法类型):

So what are method types? Quoting from §3.3.1 (MethodTypes):

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

A special case are types of methods without any parameters. They are written here => T. Parameterless methods name expressions that are re-evaluated each time the parameterless method name is referenced.

方法类型不作为值类型存在.如果将方法名称用作值,则其类型将隐式转换为相应的函数类型(§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 )状态:

以下四个隐式转换可以应用于不适用于某些参数列表的方法.

The following four implicit conversions can be applied to methods which are not applied to some argument list.

评估.类型为=> 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).

这篇关于`=&gt;的类型是什么?在Scala中使用String`吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆