I'm trying to build myself a tiny mocking library to deal with quite obvious cases:
Mock functions and record calls to them.
Mock trait implementations and be able to record calls on the methods implemented.
The first I achieved with the following implementation:
class LoggedFunction1[A1, B](body: A1 => B) extends Function1[A1, B] {
val calls = mutable.Buffer[A1]()
override def apply(v1: A1): B = {
calls += v1
body(v1)
}
}
object LoggedFunction {
def apply[A1, B](body: A1 => B) = new LoggedFunction1(body)
}
So far, so good.
I was now wondering if I could use this FunctionN extension somehow to implement the methods of a trait, such as:
trait A {
def m(i: Int)
}
class B extends A {
override def m(i: Int) = LoggedFunction((a: Int) => a)
}
Now that of course doesn't compile, because m's return value must be of type Int and not Function1[Int, Int].
I could declare a companion value to contain my information, such as:
class C extends A {
val _m = LoggedFunction((a: Int) => a)
override def m(i: Int) = _m(i)
}
But meh. What I really would like to do is:
class D extends A {
override val m = LoggedFunction((a: Int) => a)
}
In my mind the latest "should" somehow work, as I'm overriding a Function1[Int, Int] with a Function1[Int, Int], but it complains about me not overriding anything with m.
Is there any possibility I can override m using my LoggedFunction so I end up writing:
val test = new E
test.m(1)
test.m.calls should have size 1
If not: Why is it not possibly to override the method with a value containing a function?
In my mind the latest "should" somehow work, as I'm overriding a Function1[Int, Int] with a Function1[Int, Int]
Overriding a method with a function this way won't work, the two are really different things. See Functions vs methods in Scala.
In your precise use case, you could try the following:
override def m(i: Int) = LoggedFunction((a: Int) => a).apply(i)
Related
Let's say I have a specialized class and an associated companion object:
trait Slice[#specialized +T] {
...
override def equals(that :Any) = that match {
case s :Slice[_] => ???
case _ => false
}
}
object Slice {
def newInstance[#specialized T] = ???
}
Is there any way to check
Inside a method of Slice if this instance is a specialized subclass,
Inside a method of Slice if another instance is a specialized subclass for the same primitive,
Inside a specialized method on a companion object if I'm running an erased or specialized variant
without resorting to ClassTags or passing Class[_] manually? It seems like that information should be available, but the only way I can think of involves checking names of the classes.
Use case 2) is particularly important, as I could resort to faster algorithms if I knew I'm comparing apples with apples. It probably could be accomplished by reflection, but it would be quite tricky when you take into account that we have to handle non-synthetic subclasses of Slice, too; if we have also
trait ArraySlice[#specialized T] extends Slice[T] { ... }
that should be considered 'compatible' with Slice[T] instances as long as they are both specialized (or both erased)?
Ok, I figured out a cleaner way:
final val AllButUnit = new Specializable.Group((Byte, Short, Int, Long, Char, Float, Double, Boolean, AnyRef))
def specializationFor[#specialized(AllButUnit) E] :ResolvedSpecialization[E] =
Specializations(new SpecializedKey[E]).asInstanceOf[ResolvedSpecialization[E]]
private val Specializations = Seq(
resolve[Byte],
resolve[Short],
resolve[Int],
resolve[Long],
resolve[Char],
resolve[Float],
resolve[Double],
resolve[Boolean],
resolve[Unit],
resolve[AnyRef]
).map(
spec => spec.key -> spec :(SpecializedKey[_], ResolvedSpecialization[_])
).toMap.withDefaultValue(resolve[AnyRef])
private def resolve[#specialized(AllButUnit) E :ClassTag] :ResolvedSpecialization[E] =
new ResolvedSpecialization[E](new SpecializedKey[E], new Array[E](0))
class ResolvedSpecialization[#specialized(AllButUnit) E] private[SpecializedCompanion]
(val array :Array[E], val elementType :Class[E], val classTag :ClassTag[E], private[SpecializedCompanion] val key :SpecializedKey[E])
{
private[SpecializedCompanion] def this(key :SpecializedKey[E], array :Array[E]) =
this(array, array.getClass.getComponentType.asInstanceOf[Class[E]], ClassTag(array.getClass.getComponentType.asInstanceOf[Class[E]]), key)
override def toString = s"#specialized($elementType)"
override def equals(that :Any) = that match {
case r :ResolvedSpecialization[_] => r.elementType==elementType
case _ => false
}
override def hashCode = elementType.hashCode
}
private class SpecializedKey[#specialized(AllButUnit) E] {
override def equals(that :Any) = that.getClass==getClass
override def hashCode = getClass.hashCode
def className = getClass.getName
override def toString = className.substring(className.indexOf("$")+1)
}
Now specializationFor[E].elementType returns class corresponding to specialization parameter of E.
Scala allows to define update such as
def update(index: Int, value: String) { ... }
and then call it like
foo(i) = "Text"
Is there a trait that encapsulates that? Something like
trait Update1[+A,+B] {
def update(i: A, v: B)
}
(Of course I could define such a trait myself, but it would only work for instances that I mix with it, not with other ones constructed beyond my influence.)
The reason why you can't define such a trait is that you are using covariant type parameters in a place where they are not allowed. The following traits compile fine in Scala 2.10:
trait Update1[-A, -B] {
def update(i: A, v: B) : Unit
}
trait MyFunction1[-A, +B] {
def apply(a:A): B
}
trait Mutable[-A, B] extends Update1[A,B] with MyFunction1[A,B]
Notice that in order to have a mutable trait you have to fix the B parameter, so it allows neither covariance nor contravariance. If you take a look at the mutable collections in the Scala API you can see that in fact this is how they are declared.
In addition, nothing prevents you to mix a trait in an object instead of in a class to make the compiler happy, if you know that class already implements the methods defined in the trait. For example, you can have the following:
class SingleStringCollection(v: String) extends MyFunction1[Int, String] {
private var someString: String = v
def apply(a: Int): String = someString
def update(i: Int, v: String): Unit = {
someString = v
}
override def toString = someString
}
val test1: Update1[Int, String] = new SingleStringCollection("hi") // this would fail
val test2: Update1[Int, String] = new SingleStringCollection("hi") with Update1[Int, String] // this would work
Or you could also use structural typing if you just want to require that your val or parameter implements a list of known methods:
type UpdatableStructuralType = {
def update(i: Int, v: String) : Unit
}
val test3: UpdatableStructuralType = new SingleStringCollection("hi") // this would work
test3(0) = "great" // And of course this would also work
So you have several alternatives if you want to accept parameters conforming to some trait or requiring some methods to be implemented.
Suppose that I want to write a case class Stepper as follows:
case class Stepper(step: Int) {def apply(x: Int) = x + step}
It comes with a nice toStringimplementation:
scala> Stepper(42).toString
res0: String = Stepper(42)
but it's not really a function:
scala> Some(2) map Stepper(2)
<console>:10: error: type mismatch;
found : Stepper
required: Int => ?
Some(2) map Stepper(2)
A workaround is to implement the Function trait...
case class Stepper(step: Int) extends (Int => Int) {def apply(x: Int) = x + step}
But then, I can't have for free a nice toString implementation anymore:
scala> Stepper(42).toString
res2: java.lang.String = <function1>
Then, the question is: can I have the best of these two worlds? Is there a solution where I have the nice toString implementation for free AND an implementation of trait Function. In other words, is there a way to apply the linearization in such a way that case class syntaxic sugar is applied at last?
The question is not really to do with linearisation. In case-classes toString is a method automatically generated by the compiler if and only if Any.toString is not overridden in the end-type.
However, the answer is partly to do with linearisation - we need to override Function1.toString with the method that would have been generated by compiler if not for the version introduced by Function1 :
trait ProperName extends Product {
override lazy val toString = scala.runtime.ScalaRunTime._toString(this)
}
// now just mix in ProperName and... magic!
case class Stepper(step: Int) extends (Int => Int) with ProperName {
def apply(x:Int) = x+step
}
Then
println(Some(2) map Stepper(2))
println(Stepper(2))
Will produce
Some(4)
Stepper(2)
Update
Here is a version of ProperName trait that doesn't rely on the undocumented API method:
trait ProperName extends Product {
override lazy val toString = {
val caseFields = {
val arity = productArity
def fields(from: Int): List[Any] =
if (from == arity) List()
else productElement(from) :: fields(from + 1)
fields(0)
}
caseFields.mkString(productPrefix + "(", ",", ")")
}
}
Alternative toString implementation is derived from the source code for the original _toString method scala.runtime.ScalaRunTime._toString.
Please note that this alternative implementation is still based on the assumption that a case class always extends Product trait. Although the latter holds true as of Scala 2.9.0 and is a fact that is known to and relied upon by some members of Scala community it's not formally documented as part of Scala Language Spec.
EDIT: What about overriding toString?
case class Stepper(step: Int) extends (Int => Int) {
def apply(x: Int) = x + step
override def toString = "Stepper(" + step + ")"
}
You can use an implicit conversion to have Stepper treated like a function only when necessary:
case class Stepper(step: Int) { def apply(x: Int) = x + step }
implicit def s2f(s: Stepper) = new Function[Int, Int] {
def apply(x: Int) = s.apply(x)
}
Now you get the case class's toString when you call Stepper(42).toString, but Some(2) map Stepper(2) also works as desired.
(Note that I've been more verbose than necessary above to keep the mechanics clear. You can also write implicit def s2f(s: Stepper) = s.apply _ or any number of other more concise formulations).
I want to do this:
abstract class Context {
def getInt(id: Int): Int
}
abstract class Dependency[+T]
(val name: String, val id: Int)
extends Function1[Context,T]
class IntDependency(name: String, id: Int)
extends Dependency[Int](name, id) {
def apply(implicit context: Context): Int =
context.getInt(id)
}
But then I get an error message like this:
class IntDependency needs to be abstract, since method apply in trait
Function1 of type (v1: Context)Long is not defined (Note that T1 does
not match Context)
I understand that implicits should normally be part of the second parameter list, but I can't work out how to code it so it compiles, and gives the result I want.
Explanation: I'm trying to create a framework where one can define "Function" object, which can depend on other functions to compute their value. All functions should only take a single Context parameter. The context know the "result" of the other functions. The function instances should be immutable, with the state residing in the context. I want the functions to create "dependency" fields at creation time, which take the context implicitly, and return the value of the dependency within that context, so that accessing the dependency inside of the apply method "feels like" accessing a parameter or field, that is without explicitly giving the context as parameter to the dependency.
Are you sure you need your Dependency to extend a Function? Because if you don't, just leave the extends Function1[Context,T] part out and your code will work.
If you really need to extend a Function than I don't know of a solution in your case. But there are cases where you could try to overload the apply method. Like here:
scala> val sum = new Function1[Int, Function1[Int, Int]] {
| def apply(a: Int) = (b: Int) => a + b
| def apply(a: Int)(implicit b: Int) = a + b
|}
sum: java.lang.Object with (Int) => (Int) => Int{def apply(a:Int)(implicit b: Int): Int} = <function1>
scala> sum(2)(3)
res0: Int = 5
scala> implicit val b = 10
b: Int = 10
scala> sum(2)
res1: Int = 12
A method may have its final parameter section marked implicit; it need not be the second section, although that is most commonly seen.
But it seems that when a subclass marks a parameter section implicit, it is no longer considered to override the method in the superclass.
scala> new (Int => Int) { def apply(implicit i: Int) = i }
<console>:8: error: object creation impossible, since method apply in trait Function1 of type (v1: Int)Int is not defined
(Note that T1 does not match Int)
new (Int => Int) { def apply(implicit i: Int) = i }
^
scala> trait F1 { def f(a: Any) }; new F1 { def f(implicit a: Any) = () }
<console>:8: error: object creation impossible, since method f in trait F1 of type (a: Any)Unit is not defined
trait F1 { def f(a: Any) }; new F1 { def f(implicit a: Any) = () }
^
The spec does not specifically mention this (§5.1.4 Overriding), so it may be an implementation restriction, or an bug.
Its sure, that your apply method signature with implicit doesn´t conform with the signature of Function1.apply.
Hopefully I get your problem right, so what about (assuming that your context is mutable and perhaps singleton) having the implicit context injected at creation time? Is that possible in your case?
class IntDependency(id: Int)(implicit context: Context) extends Dependency[Int](id)
But then I wonder (and still was wondering before) what to do with the context argument at the apply method.
Here is the working solution:
abstract class Context {
def getInt(id: Int): Int
}
abstract class Dependency[+T]
(val name: String, val id: Int) {
def get(context: Context): T
}
class IntDependency(name: String, id: Int)
extends Dependency[Int](name, id) {
def get(context: Context): Int =
context.getInt(id)
}
implicit def intDep2Int(dep: IntDependency)
(implicit context: Context): Int =
dep.get(context)
I have a class that takes an implicit parameter which is used by functions called inside class methods. I want to be able to either override that implicit parameter, or alternatively, have the implicit argument be copied from its source. As an example:
def someMethod()(implicit p: List[Int]) {
// uses p
}
class A()(implicit x: List[Int]) {
implicit val other = List(3) // doesn't compile
def go() { // don't want to put implicit inside here since subclasses that override go() have to duplicate that
someMethod()
}
}
The behavior I want is that someMethod() gets an implicit parameter that is some changed version of x, which was the class's implicit parameter. I want to be able to either mutate x without changing it for whatever passed it into A's constructor, or otherwise override it to a new value of my choosing. Both approaches don't seem to work. That is, it doesn't copy the list in the former case, and the compiler finds an ambiguous implicit value for the latter case. Is there a way to do this?
I realize that I can redefine the implicit value within go(), but this is not a good choice in my case because this class is subclassed numerous times, and I'd like to handle this implicit change in the base class only. So it doesn't necessarily need to go in the constructor, but it must be in a method other than go().
Introduce another wrapper type, simply to disambiguate:
// badly named, choose something domain-specific
case class ListHolder(theList: List[Int])
def someMethod()(implicit holder: ListHolder) {
val xs = holder.theList
// uses xs ...
}
class A()(implicit xs: List[Int]) {
implicit val other = ListHolder(42 :: xs) // compiles
def go() {
// xs is never considered for the implicit param to someMethod()
// because it's now the wrong type
}
}
This also makes the code more self-documenting, as it becomes blindingly obvious that the two implicits are not one and the same.
If you want to have zillions of implicits floating around that don't collide with each other, you can create a wrapper class that you can tag with marker traits for implicit usage. There are a variety of syntaxes you could use; here's one example:
object Example {
class Implication[A,B](val value: A) {
def apply[C](c: C) = new Implication[C,B](c)
}
object Implication {
def mark[B] = new Implication[Unit,B](())
implicit def implication_to_value[A,B](i: Implication[A,B]) = i.value
}
trait One {}
trait Two {}
implicit val x = Implication.mark[One]("Hello")
implicit val y = Implication.mark[Two]("Hi")
def testOne(implicit s: Implication[String,One]) = println(s: String)
def testTwo(implicit s: Implication[String,Two]) = println(s: String)
def testThree(s: String) = println("String is " + s)
def main(args: Array[String]) {
testOne
testTwo
testThree(x)
testThree(y)
}
}
Which works as you would hope:
scala> Example.main(Array())
Hello
Hi
String is Hello
String is Hi
Since you have to use a wrapper object, it's not super-efficient, but it can be very effective. (Or very confusing, given how much happens implicitly.)
This modification compiles. I changed x into a var:
class A()(implicit var x: List[Int]) {
def someMethod()(implicit p: List[Int]) {
// uses p
}
x = List(3)
def go() { // don't want to put implicit inside here since subclasses that override go() have to duplicate that
someMethod()
}
}