当Scala中的anonfun$1变为anonfun$m1$1(或反之亦然)时?

当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,而

有人能解释为什么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
,而下面给出了
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,除非目前它并不比我们聪明