Получаване на препратка към параметър на външната функция с противоречиво име

Моля, разгледайте този код:

trait A {
  def a : Int
}

def f ( a : Int ) = {
  def a0 = a
  new A {
    def a = a0
  }
}

Проблемът е доста очевиден: def a0 = a е типичен досаден шаблонен код и ситуацията само се влошава, когато се въведат повече параметри.

Чудя се дали е възможно по някакъв начин да получа директна препратка към променливата a на външния обхват вътре в декларацията на екземпляра на чертата и по този начин да се отърва от междинния a0.

Моля, имайте предвид, че промяната на името на входния параметър на функцията не е разрешена, както и промяната на характеристиката.


person Nikita Volkov    schedule 01.09.2012    source източник


Отговори (3)


Не мисля, че има директен начин да се направи това, защото ще изисква някакъв специален (хипотетичен) идентификатор thisMethod. Въпреки това, в зависимост от вашия контекст, може да са възможни следните два начина за избягване на засенчването на името:

(1) Заменете анонимния клас A с изпълняващ клас:

case class AImpl(a: Int) extends A

def f(a : Int): A = AImpl(a)

(2) Дефинирайте f в абстрактна характеристика и използвайте конкретна реализация за него:

trait F {
  def f(a: Int): A
}

object FImpl extends F {
  def f(a0: Int): A = new A { val a = a0 }
}

def test(factory: F): A = factory.f(a = 33)
person 0__    schedule 01.09.2012

Мисля, че най-близкото, до което можете да стигнете (без да променяте своя API), е:

def f(a: Int) = {
  def ff(a0: Int) = {
    new A {
      def a = a0
    }
  }
  ff(a)
}

В Scala методите не са типове. По този начин не е възможно да се препратят към тях с типовата система или някой от нейните членове.

scala> class X{def f = 0}
defined class X

scala> import reflect.runtime.universe._
import reflect.runtime.universe._

scala> typeOf[X].member(newTermName("f")).isType
res9: Boolean = false
person kiritsuku    schedule 01.09.2012

Ето едно анонимно решение.

package eyeshadow

trait A {
  def a: Int
}

class B {
  def f(a: Int) = {
    val fa: A = new {
      //private val b = a
      private[this] val b = a // crashes, sorry scalac. edit: ok in 2.11
    } with A {
      def a = b
    }
    fa.a
    /*
     * This seems far-fetched, but compare the initial objections in
     * https://issues.scala-lang.org/browse/SI-3836
     * All I want is to alias a symbol, right?
     * Maybe the override means "do not shadow."
    val fa: A = new A {
      //import fa.{ a => b }
      import this.{ a => b }
      override def b = a
    }
     */
  }
}

object Test {
  def main(args: Array[String]) {
    val b = new B
    println(b f 7)
  }
}
person som-snytt    schedule 02.09.2012