Получение ссылки на параметр внешней функции с конфликтующим именем

Пожалуйста, рассмотрите этот код:

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