当Scala中的anonfun$1变为anonfun$m1$1(或反之亦然)时?
有人能解释为什么Scala在以下情况下给出两个不同的名称吗?为什么Scala不能在每个案例中给出相同的名称?!是否有某种我还不知道的一致性?这一定和eta的扩张有关吧当Scala中的anonfun$1变为anonfun$m1$1(或反之亦然)时?,scala,scalac,Scala,Scalac,有人能解释为什么Scala在以下情况下给出两个不同的名称吗?为什么Scala不能在每个案例中给出相同的名称?!是否有某种我还不知道的一致性?这一定和eta的扩张有关吧 object A { val ms: Seq[String => String] = Seq(m1) def m1(s: String) = s } A.ms.map(m => m.getClass.getSimpleName) 上面给出了List(anonfun$1)-注意元素的名称-anonfun$1,而
object A {
val ms: Seq[String => String] = Seq(m1)
def m1(s: String) = s
}
A.ms.map(m => m.getClass.getSimpleName)
上面给出了List(anonfun$1)
-注意元素的名称-anonfun$1
,而下面给出了anonfun$m1$1
。为什么?
object A {
val ms: Seq[String => String] = Seq(m1)
def m1: String => String = s => s
}
A.ms.map(m => m.getClass.getSimpleName)
我还可以要求一个更简单的例子来说明差异(也许不使用
Seq
)?似乎编译器在创建匿名类时会在名称中添加路径。您的示例(顺便说一句,在其他意义上相当有趣)可以简化为:
def m1(s: String) = s
def m2: String => String = s => s
val ss: Seq[String => String] = Seq(m1, m2)
ss map (_.getClass.getSimpleName)
产生:
res28: Seq[String] = List(anonfun$1, anonfun$m2$1)
无以下内容:
(m1 _).getClass.getSimpleName
res34: String = anonfun$1
m2.getClass.getSimpleName
res35: String = anonfun$m2$1
幸运的是,Seq中的m1
相当于m1
,m2
相当于方法应用。
名称呢?编译器将路径添加到自动生成的类中,因此,顶级作用域m1
变为anonfun$1
(anonfun是函数的生成类的默认前缀),并且由于m2
从内部返回函数,该函数在路径(名称)中又获得一个元素
有趣的是,这件奇怪的事:
def a() = {
def b() = {
def c() = {
def d(): String => String = s => s
d()
}
c()
}
b()
}
姓名:
a().getClass.getSimpleName
res30: String = anonfun$d$1$1
所以,没有a,b,c的痕迹!所以,这有点复杂,我尝试过,但在编译器源代码中找不到命名的确切选择和模式,尽管阅读很有趣。似乎编译器在创建匿名类时会在名称中添加路径。您的示例(顺便说一句,在其他意义上相当有趣)可以简化为:
def m1(s: String) = s
def m2: String => String = s => s
val ss: Seq[String => String] = Seq(m1, m2)
ss map (_.getClass.getSimpleName)
产生:
res28: Seq[String] = List(anonfun$1, anonfun$m2$1)
无以下内容:
(m1 _).getClass.getSimpleName
res34: String = anonfun$1
m2.getClass.getSimpleName
res35: String = anonfun$m2$1
幸运的是,Seq中的m1
相当于m1
,m2
相当于方法应用。
名称呢?编译器将路径添加到自动生成的类中,因此,顶级作用域m1
变为anonfun$1
(anonfun是函数的生成类的默认前缀),并且由于m2
从内部返回函数,该函数在路径(名称)中又获得一个元素
有趣的是,这件奇怪的事:
def a() = {
def b() = {
def c() = {
def d(): String => String = s => s
d()
}
c()
}
b()
}
姓名:
a().getClass.getSimpleName
res30: String = anonfun$d$1$1
所以,没有a,b,c的痕迹!因此,这有点复杂,我尝试过,但在编译器源代码中找不到命名的确切选择和模式,尽管阅读很有趣。您可以观察到符号操作:
$ scala -Yshow-syms -uniqid -Dscala.repl.maxprintstring=8000
在REPL中,需要预先警告的是,您将看到包装代码的一令输出,然后是打印结果的代码位的第二令输出
scala> def m1: String => String = s => s
[[symbol layout at end of parser]]
* package scala#22 (final)
[[symbol layout at end of namer]]
* object $read#58183
* package $line6#58181 (final)
package scala#22 (final)
[[symbol layout at end of packageobjects]]
object $read#58183
package $line6#58181 (final)
package scala#22 (final)
[[symbol layout at end of typer]]
* class String#643 (final)
* constructor Object#3505
* object $read#58184
* constructor $read#58188
* object $iw#58190
* constructor $iw#58192
* object $iw#58193
* object $iw#58194
* constructor $iw#58196
* method m1#58197
* value $anonfun#58199 (<synthetic>)
* value s#58200
但是由于newName
无论如何都会得到一个新名称,我想保留方法名称是一种调试帮助
它是一个很好的调试辅助工具吗
编译单元中任何方法“m”中的多个anonfun都将被命名为anonfun$m$1
,依此类推;除了检查这些类别外,无法区分anonfun$m$3
是否属于Foo.m
或Bar.m
我会依靠REPL来为我发现新的符号,但目前它并不比我们聪明。你可以观察到符号操纵:
$ scala -Yshow-syms -uniqid -Dscala.repl.maxprintstring=8000
在REPL中,需要预先警告的是,您将看到包装代码的一令输出,然后是打印结果的代码位的第二令输出
scala> def m1: String => String = s => s
[[symbol layout at end of parser]]
* package scala#22 (final)
[[symbol layout at end of namer]]
* object $read#58183
* package $line6#58181 (final)
package scala#22 (final)
[[symbol layout at end of packageobjects]]
object $read#58183
package $line6#58181 (final)
package scala#22 (final)
[[symbol layout at end of typer]]
* class String#643 (final)
* constructor Object#3505
* object $read#58184
* constructor $read#58188
* object $iw#58190
* constructor $iw#58192
* object $iw#58193
* object $iw#58194
* constructor $iw#58196
* method m1#58197
* value $anonfun#58199 (<synthetic>)
* value s#58200
但是由于newName
无论如何都会得到一个新名称,我想保留方法名称是一种调试帮助
它是一个很好的调试辅助工具吗
编译单元中任何方法“m”中的多个anonfun都将被命名为anonfun$m$1
,依此类推;除了检查这些类别外,无法区分anonfun$m$3
是否属于Foo.m
或Bar.m
我会依靠REPL为我发现另一个UNFUNS,除非目前它并不比我们聪明