Please consider this code:
trait A {
def a : Int
}
def f ( a : Int ) = {
def a0 = a
new A {
def a = a0
}
}
The problem is quite evident: def a0 = a
is a typical annoying boilerplate code and the situation only worsens when more parameters get introduced.
I am wondering if it's possible to somehow get a direct reference to the a
variable of the outer scope inside the declaration of the instance of the trait and thus to get rid of the intermediate a0
.
Please keep in mind that changing name of input parameter of the function is not allowed as is changing the trait.
I don't think there is direct way to do that, because it would require some special (hypothetical) identifier thisMethod
. However, depending on your context, the following two ways to avoid the name shadowing might be possible:
(1) Replace anonymous class A
with implementing class:
case class AImpl(a: Int) extends A
def f(a : Int): A = AImpl(a)
(2) Define f
in an abstract trait and use a concrete implementation for it:
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)
I think the closest you can get to (without changing your API) is:
def f(a: Int) = {
def ff(a0: Int) = {
new A {
def a = a0
}
}
ff(a)
}
In Scala, methods are not types. Thus, it is not possible to reference them with the type system or any of there members.
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
Here is an anonymous solution.
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)
}
}