2013-11-30 6 views
0

Может ли кто-нибудь объяснить, почему Scala дает два разных имени в следующих случаях? Почему Scala не дает одинаковых имен в каждом случае ?! Есть ли какая-то последовательность, которую я еще не знаю? Это должно быть связано с эта-расширением, верно?

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

ответ

1

Кажется, компилятор добавляет путь в имя при создании анонимных классов. Ваш пример (довольно интересно в каком-то другом смысле, кстати) может быть упрощено до:

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 

К счастью m1 в послед эквивалентно m1 _, а m2 эквивалентно применению метода. Что касается имен - компилятор добавляет путь к автогенерированным классам, поэтому верхняя область m1 превращается в anonfun$1 (anonfun является префиксом по умолчанию для сгенерированных классов для функций), а потому, что возвращает функцию изнутри, эта функция получает еще один элемент в пути (имя).

Интересно, что эта странная вещь:

def a() = { 
    def b() = { 
    def c() = { 
     def d(): String => String = s => s 
     d() 
    } 
    c() 
    } 
    b() 
} 

Имеет имя:

a().getClass.getSimpleName 
res30: String = anonfun$d$1$1 

Таким образом, нет следов, Ь, с! Итак, это несколько сложно, я попытался, но не смог найти точный выбор и шаблоны именования в источнике компилятора, хотя чтение было интересным.

1

Вы можете наблюдать манипуляции символов:

$ scala -Yshow-syms -uniqid -Dscala.repl.maxprintstring=8000 

В РЕПЛ, предупреждают, вы увидите одну пачки продукции для завернутой коды, а затем второй стопу выхода для бита кода, который печатает ваш результат.

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 

... массивный надрез ...

  object $iw#58194 
       constructor $iw#58196 
       method m1#58197 
        <$anon: Function1#2093> (final <synthetic>) 
         constructor $anonfun#58218 


[[symbol layout at end of lambdalift]] 

... чик ...

  object $iw#58194 
O    <$anon: Function1#2093> [Owner was method m1#58197, now object $iw#58194] (final <synthetic>) 
        constructor $anonfun$m1$1#58218 

Как говорит выход, то anonfun становится дочерним объемлющего класса потому что он реализуется как класс; любые захваченные переменные передаются его конструктору.

Быстрый просмотр LambdaLift.scala показывает, что newName фактически special-cases anonymous functions that are owned by methods, чтобы иметь название, которое вы указали.

Это простой способ избежать конфликтов имен, таких как:

scala> class Foo { def x = 1 to 10 map (2 * _) ; def y = 1 to 10 map (3 * _) filter (_ > 6) } 

Но поскольку newName получает свежее имя в любом случае, я бы предположил, что сохранение имени метода является доводка помощь.

Хорошая ли отладочная помощь?

Несколько анонимных в любом методе 'm' в компиляционной единице будут называться anonfun$m$1 и так далее; нет способа отличить, принадлежал ли anonfun$m$3Foo.m или Bar.m, за исключением проверки этих классов.

Я бы положился на REPL, чтобы открыть для меня anonfuns, за исключением того, что в настоящее время он не умнее, чем мы.

 Смежные вопросы

  • Нет связанных вопросов^_^