加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

发布时间:2020-12-16 09:07:07 所属栏目:安全 来源:网络整理
导读:在 scala中,有一些按名称调用的参数: def hello(who: = String) = println("hello," + who) 参数的类型是什么? 它将scala REPL上的函数显示为: hello: (who: = String)Unit 类型仍然是=串?它有什么名字吗?或者一些描述类型的文档? answer提出的进一步
在 scala中,有一些按名称调用的参数:

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

参数的类型是什么?

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

hello: (who: => String)Unit

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

answer提出的进一步问题

问题1

(当阅读§3.3.1(MethodTypes)的规范时)

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

def hello: String = "abc"

它的类型可以写成:=>字符串,对吗?虽然你可以看到REPL响应是:

scala> def hello:String = "abc"
hello: String

如果我定义一个具有参数的方法:

def goodname(name: String): String = name + "!"

方法的类型是什么?它应该类似于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 =>字符串,对吗?

但对于无所畏惧的方法:

def hello: String = "abc"

可以转换哪种函数类型?我试过了:

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

但这不能编译:

print(hello)

错误是:

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

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

问题3

(当阅读§6.26.2(MethodConversions)的规范时)

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

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

我的问题是,当我打电话给print(myname)时,是否有转换(我的意思是评估转换)?我猜,因为myname的类型只是=>字符串,因此可以直接传递给它.

如果打印方法已更改:

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

这里的评估转换肯定发生了,对吧?(From => String to String)

解决方法

引自 §4.6.1 of the spec:

The type of such a parameter is then the parameterless method type => T.

因此,按名称调用param的类型是(近似)()=> T(如果您愿意,可以是Function0 [T]).如果你:javap接受一个call-by-name参数的方法,你将看到编译的代码接受scala.Function0< java.lang.Object>类型的param.

近似的一个例子

翻译:

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
????????})

?也就是说,不是传入返回Int的Function0,而是传递一个Function0,它返回一个返回Int的Function0.

什么=>实际上是

=> T实际上是一种方法类型,而不是一个对象.因此,之前的所有内容都是编译器所做的事情的近似,并且可以随时更改.引自§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 (MethodTypes):

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.

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 (07003).

§6.26.3 (MethodConversions)州:

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

Evaluation. A parameterless method m of type => T is always converted to type T by evaluating the expression to which m is bound.

所以type =>的正确翻译总是:

def random$name$here: T

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

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

尝试新的TestParamless().示例以及:javap TestParamless(在scala REPL中).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读