If I have the following code:
trait MyTrait {
val x: Int
}
def f(_x: Int) = new MyTrait {
val x = _x
}
If I were to define my function as follows:
def f(x: Int) = new MyTrait {
val x = x
}
This would be incorrect as val x is just referring to itself. Is there a way I can avoid having to use a different name for 'x' when I want to refer to something in the outer scope?
You can, but only if the outer scope x is a member of enclosing type, not a method parameter or a local variable:
class MyOuter(val x: Int) {
def f() = new MyTrait {
val x = MyOuter.this.x
}
Not really: in the scope of MyTrait, x refers to the field. However, you have the option to wrap parameter into some other name before you enter that scope:
def f(x: Int) = {
val xn = x
new MyTrait {
val x = xn
}
}
Well, in this particular case, you could write something like this:
def f(x: Int) = {
class Foo(val x: Int = x) extends MyTrait
new Foo
}
Not sure what exactly it makes better over just renaming x to y though ...
Related
I am trying to write a scala-wrapper for matrix operations, using the ejml library. Basically I just use SimpleMatrix. However, I want different classes for matrix and vector, for example to only be able to invert a matrix or to explicitly state that a function returns a vector, not a matrix. Currently, I am having trouble returning the concrete classes instead of the trait.
I started with a trait, MLMatrixLike:
trait MLMatrixLike {
def data: SimpleMatrix
protected def internalMult(implicit that: MLMatrixLike): SimpleMatrix = {
data.mult(that.data)
}
def *(implicit that: MLMatrixLike): MLVector = MLVector(internalMult)
}
Both my matrix class and my vector class are extending the trait:
case class MLMatrix(data: SimpleMatrix) extends MLMatrixLike {
def this(rawData: Array[Array[Double]]) = this(new SimpleMatrix(rawData))
def apply(row: Int, col:Int): Double = data.get(row, col)
def transpose(): MLMatrix = MLMatrix(data.transpose())
def invert(): MLMatrix = MLMatrix(data.invert())
def *(implicit that: MLMatrix): MLMatrix = MLMatrix(internalMult)
def *(that: Double): MLMatrix = MLMatrix(data.scale(that))
def -(that: MLMatrix): MLMatrix = MLMatrix(data.minus(that.data))
}
object MLMatrix {
def apply(rawData: Array[Array[Double]]) = new MLMatrix(rawData)
}
case class MLVector(data: SimpleMatrix) extends MLMatrixLike {
def this(rawData: Array[Double]) = {
this(new SimpleMatrix(Array(rawData)).transpose())
}
def apply(index: Int): Double = data.get(index)
def transpose(): MLVector = MLVector(data.transpose())
def -(that: MLVector): MLVector = MLVector(data.minus(that.data))
}
object MLVector {
def apply(rawData: Array[Double]) = new MLVector(rawData)
}
To my mind, this setup is not very good. I would like to define multiply (*) only once, since the SimpleMatrix-call is always the same and I can infer from the type of the parameter "that" whether the return type should be a matrix or a vector. Thus I would like to define a single function in MLMatrixLike along the lines of this (not working) function:
def *[T <: MLMatrixLike](that :T): T = {
new T(data.mult(that.data))
}
Of course, this does not work, since there is no such constructor T, but currently I fail to see, how I can get something similar to work. Returning MLMatrixLike is not correct to my mind, since that way I cannot check during compilation if the correct type is returned.
A similar problem applies to transpose, and minus - here the return type is always the own class.
Thank you very much!
I'm not sure what the benefits of wrapping SimpleMatrix in two other classes are. However, you could solve the duplication problem by making MLMatrixLike generic with its self-type, and defining an abstract constructor.
trait MLMatrixLike[Self <: MLMatrixLike[Self]] {
this: Self =>
def data: SimpleMatrix
def createNew(data: SimpleMatrix): Self
def *[T <: MLMatrixLike[T]](that: T): T = that.createNew(data.mult(that.data))
def *(that: Double): Self = createNew(data.scale(that))
def -(that: Self): Self = createNew(data.minus(that.data))
def transpose: Self = createNew(data.transpose())
}
case class MLMatrix(data: SimpleMatrix) extends MLMatrixLike[MLMatrix] {
this: MLMatrix =>
def this(rawData: Array[Array[Double]]) = this(new SimpleMatrix(rawData))
override def createNew(data: SimpleMatrix): MLMatrix = MLMatrix(data)
def apply(row: Int, col: Int): Double = data.get(row, col)
def invert(): MLMatrix = MLMatrix(data.invert())
}
object MLMatrix {
def apply(rawData: Array[Array[Double]]) = new MLMatrix(rawData)
}
case class MLVector(data: SimpleMatrix) extends MLMatrixLike[MLVector] {
this: MLVector =>
def this(rawData: Array[Double]) = {
this(new SimpleMatrix(Array(rawData)).transpose())
}
override def createNew(data: SimpleMatrix): MLVector = MLVector(data)
def apply(index: Int): Double = data.get(index)
}
object MLVector {
def apply(rawData: Array[Double]) = new MLVector(rawData)
}
By the way, note, that a column vector times a row vector is a matrix, so the signature of the multiplication should probably not return the type of that. However, based on static information (you need to know the dimensions of both arguments) you cannot tell whether a multiplication returns a vector or a matrix, so you may aswell just return a MLMatrixLike.
I have a use case similar to the situation following:
trait A {
implicit val x = "hello"
}
class B {
// somehow bring x into scope here???
def run(x: Int)(implicit y: String) = y + x
}
println((new B).run(3))
I understand that I need to bring x defined in the trait in the implicit scope of B. I've already tried the following:
# attempt 1 #
class B extends A { .... } /// doesn't work
# attempt 2 #
class B extends A {
val x1 = implicitly[String] /// doesn't work either
def run(x: Int)(implicit y: String) = y + x
}
Please explain what am I missing here (or, point me to relevant theory topic which I can study, fairly new to scala).
The value of 'implicit y' will be resolved in your println-line where it is not available. You are making the variable implicitly available within the body of the class, but resolution of implicit String is not needed there.
Implicit isn't magic; if you can't reach the implicit variable explicitly then so can't the compiler.
What problem are you really trying to solve?
Wrap your whole code in a object and extend trait A in class B :
object P {
trait A {
implicit val x = "hello"
}
class B extends A {
def run(y: Int) = y + x
}
def f = println(new B().run(3))
}
Output :
scala> P.f
3hello
I have a trait and a case class implementing it. One of the features of the trait that the implementations override is a default value. I can't find a good way to access this default value from a class that is parametrized by a specific implementation of that trait.
This is minimal code, so it doesn't really demonstrate the motivation anymore, but it does demonstrate the error:
import scala.language.implicitConversions
trait Distance[T] {
val Zero: T
def +( that: T ): T
}
case class DoubleDistance( val v: Double ) extends Distance[DoubleDistance] {
val Zero = DoubleDistance( 0.0 )
def +( that: DoubleDistance ) = DoubleDistance( v + that.v )
}
object DistanceImplicits {
implicit def DoubleToDistance( v: Double ) = new DoubleDistance( v )
}
class User[T<:Distance[T]] {
val default: T = T.Zero // This line gives me a compilation error
}
The error I get is
not found: value T
When I needed to construct an Array[T] inside my User class I could get that to work by adding implicit typetag:ClassTag[T] to my arguments, but that doesn't seem to have any effect here.
First, why this doesn't work: consider a different implementation of Distance.
case class DoubleDistance1(val v: Double) extends Distance[DoubleDistance1] {
val Zero = this
def +(that: DoubleDistance1) = ??? // doesn't matter
}
What would you expect DoubleDistance1.Zero to mean? You can make it work using a "type class":
trait DistanceOps[T] {
val zero: T
def add(d1: T, d2: T): T
}
// just to let you write distance1 + distance2
implicit class RichDistance[T](d: T)(implicit ops: DistanceOps[T]) {
def +(other: T) = ops.add(d, other)
}
case class DoubleDistance(v: Double)
object DoubleDistance {
implicit object DoubleDistanceOps extends DistanceOps[DoubleDistance] {
val zero = DoubleDistance(0.0)
def add(d1: DoubleDistance, d2: DoubleDistance) = DoubleDistance(d1.v + d2.v)
}
}
// how to use
class User[T](implicit ops: DistanceOps[T]) {
val default: T = ops.zero
}
This looks like a classic use case for the type class pattern. Rather than associating an instance of the Distance trait with each value of interest, you associate one with each type of interest:
trait Distance[T] {
val Zero: T
def +( a: T, b: T ): T
}
implicit object DoubleDistance extends Distance[Double] {
val Zero = 0.0
def +( a: Double, b: Double ) = a + b
}
class User[T : Distance] {
val default: T = implicitly[Distance[T]].Zero
}
Where is that Zero supposed to come from? Are you looking to do something like this?
class User[T<:Distance[T]] {
self:Distance[T] =>
val default: T = Zero
}
Here's a common annoyance for me:
trait Foo {
val x: Int
}
def foo(x: Int) = new Foo {
val x = x // <-- Here
}
I probably run into this about once every 20 minutes when coding Scala.
The solutions that I am aware of, and their respective deficiencies, are:
Enclose the local declaration in an object which can be named -- Doesn't work for parameters.
Make an alias -- Verbose if you need to preserve the path dependent type.
Use a proxy constructor -- Cumbersome in the presence of dependently typed fields.
Are there any others?
I sometimes use this cheesy approach:
def foo(x: Int): Foo = {
val x1 = x
new Foo {
val x = x1
}
}
How about this?
trait Foo {
val x: Int
}
object Foo {
def apply(xt: Int) = new Foo { val x = xt }
}
def foo(xt: Int) = Foo(xt) // <-- Here
Suppose an outer class with an inner composite of two inner classes:
class Outer(val times: Int) {
class Inner(val count: Int)
object Inner {
def apply(i: Int) = new Inner(i)
}
class InnerWrap(val i: Inner)
object InnerWrap {
def apply(i: Inner) = new InnerWrap(i)
}
def method(i: Inner) = i.count * times
}
object Outer {
def apply(times: Int) = new Outer(times)
}
class PathDependentExpl {
val o = new Outer(3)
val i = o.Inner(2)
val p = new Outer(5)
val j = p.Inner(3)
println(o.method(i))
println(p.method(j))
}
All nice and dandy. We even have compiler protection against feeding inners from one Outer to methods of another Outer through path-dependent types.
But the syntax is a little annoying. I want to be able to write something like
implicit val p = new Outer(5)
val k = Inner(3) // same as p.Inner(3)
val l = InnerWrap(Inner(3))
...omitting the outer instance for the block where the implicit is valid. So I rush adding delegate methods with the Outer object as an implicit parameter.
object Outer {
def apply(times: Int) = new Outer(times)
def Inner(c: Int)(implicit o: Outer) = o.Inner(c)
def InnerWrap(i: o.Inner)(implicit o: Outer) = o.InnerWrap(i)
}
That last InnerWrap definition yields: "illegal dependent method type: parameter appears in the type of another parameter in the same section or an earlier one", which actually makes sense. I tried def InnerWrap[O <: Outer#Inner](i: O)(implicit o: Outer) = o.InnerWrap(i) and other variants to no avail.
Question is, how can I still get to use the cleaner syntax? How can the declaration of InnerWrap in object Outer can be made to accept o.Inners or equivalent?
As I noted in a comment above, it's possible to import the objects (or methods) you need from p, which may give you the clean syntax you're looking for:
scala> val p = new Outer(5)
p: Outer = Outer#4fe2fe5d
scala> import p._
import p._
scala> val k = Inner(3)
k: p.Inner = Outer$Inner#b90ffa7
scala> val l = InnerWrap(Inner(3))
l: p.InnerWrap = Outer$InnerWrap#3bd6bff7