Scala SetBuffer - scala

I am trying to update my project from Scala 2.12 to Scala 2.13. I see that the Scala team has done a lot of changes on the collection side.
I have a SetBuffer that looks like this in Scala 2.12
object SetBuffer extends MutableSetFactory[SetBuffer] {
override def empty[Elem] = new SetBuffer[Elem](Set.empty)
def apply[Elem](initialSet: Iterable[Elem]): SetBuffer[Elem] =
new SetBuffer[Elem](initialSet.toSet)
override def newBuilder[Elem] = new SetBufferBuilder[Elem]()
class SetBufferBuilder[Elem] extends mutable.GrowingBuilder[Elem, SetBuffer[Elem]](SetBuffer.empty) {
override def result(): SetBuffer[Elem] =
new SetBuffer[Elem](elems.getDelta)
}
}
class SetBuffer[ElemType](initialSet: Set[ElemType])
extends mutable.HashSet[ElemType]
with mutable.SetLike[ElemType, SetBuffer[ElemType]]
with GenericSetTemplate[ElemType, SetBuffer] {
initialSet.map(+=)
override def companion: SetBuffer.type = SetBuffer
def getDeltaBuffer: SetBuffer[ElemType] = {
SetBuffer[ElemType]((this -- initialSet).toSeq:_*)
}
def getDelta: immutable.Set[ElemType] = {
val deltaElements = (this -- initialSet).toSeq
immutable.Set[ElemType](deltaElements: _*)
}
def ++(that: Iterable[ElemType]): SetBuffer[ElemType] =
SetBuffer(toIterable ++ that)
def append(that: Iterable[ElemType]): Unit = this ++= that
def ++=(that: Iterable[ElemType]): Unit = that.map(+=)
}
Scala 2.13 removed mutable.SetLike[ElemType, SetBuffer[ElemType]] and GenericSetTemplate[ElemType, SetBuffer] and made mutable.HashSet final. Is there a way to rewrite the code in the class SetBuffer[ElemType](initialSet: Set[ElemType]) so it will behave the same and have the same performances?

Two ideas come to my mind.
First - you can try to use https://www.scala-lang.org/api/current/scala/collection/mutable/LinkedHashSet.html that seems to not be final. I am not sure if it's possible and I didn't search for performance characteristics.
Second, you go for composition over inheritance. Wrap the instance of HashSet and delegate all calls to it. You would have to implement quite a few interfaces to achieve the same behaviour though.

Related

Way to enhance a class with function delegation

I have the following classes in Scala:
class A {
def doSomething() = ???
def doOtherThing() = ???
}
class B {
val a: A
// need to enhance the class with both two functions doSomething() and doOtherThing() that delegates to A
// def doSomething() = a.toDomething()
// def doOtherThing() = a.doOtherThing()
}
I need a way to enhance at compile time class B with the same function signatures as A that simply delegate to A when invoked on B.
Is there a nice way to do this in Scala?
Thank you.
In Dotty (and in future Scala 3), it's now available simply as
class B {
val a: A
export a
}
Or export a.{doSomething, doOtherThing}.
For Scala 2, there is unfortunately no built-in solution. As Tim says, you can make one, but you need to decide how much effort you are willing to spend and what exactly to support.
You can avoid repeating the function signatures by making an alias for each function:
val doSomething = a.doSomething _
val doOtherthing = a.doOtherThing _
However these are now function values rather than methods, which may or may not be relevant depending on usage.
It might be possible to use a trait or a macro-based solution, but that depends on the details of why delegation is being used.
Implicit conversion could be used for delegation like so
object Hello extends App {
class A {
def doSomething() = "A.doSomething"
def doOtherThing() = "A.doOtherThing"
}
class B {
val a: A = new A
}
implicit def delegateToA(b: B): A = b.a
val b = new B
b.doSomething() // A.doSomething
}
There is this macro delegate-macro which might just be what you are looking for. Its objective is to automatically implement the delegate/proxy pattern, so in your example your class B must extend class A.
It is cross compiled against 2.11, 2.12, and 2.13. For 2.11 and 2.12 you have to use the macro paradise compile plugin to make it work. For 2.13, you need to use flag -Ymacro-annotations instead.
Use it like this:
trait Connection {
def method1(a: String): String
def method2(a: String): String
// 96 other abstract methods
def method100(a: String): String
}
#Delegate
class MyConnection(delegatee: Connection) extends Connection {
def method10(a: String): String = "Only method I want to implement manually"
}
// The source code above would be equivalent, after the macro expansion, to the code below
class MyConnection(delegatee: Connection) extends Connection {
def method1(a: String): String = delegatee.method1(a)
def method2(a: String): String = delegatee.method2(a)
def method10(a: String): String = "Only method I need to implement manually"
// 96 other methods that are proxied to the dependency delegatee
def method100(a: String): String = delegatee.method100(a)
}
It should work in most scenarios, including when type parameters and multiple argument lists are involved.
Disclaimer: I am the creator of the macro.

How to call an overriden method using reflection?

Consider we have the following:
class Base { def name = "Base" }
class Successor extends Base {
override def name = "Successor"
}
I have tried to do the following (took from How to call a superclass method using Java reflection):
import java.lang.invoke.{MethodHandles, MethodHandle, MethodType}
object TestApp {
def main(args: Array[String]) {
val a = new Successor;
val h1 = MethodHandles.lookup().findSpecial(classOf[Base],
"name",
MethodType.methodType(classOf[String]),
classOf[Successor]);
println(h1.invoke(a));
}
}
but I get a runtime exception:
java.lang.IllegalAccessException: no private access for invokespecial: class Successor, from TestApp$
I was told that it is possible that Java reflection may not work correctly for Scala. Is it true? Or I simply do something wrong?
Actually, you can NOT even do it in Java. Note, in the answer of "How to call a superclass method using Java reflection", it works because the Test extends the Base: public class Test extends Base {...}.
It looks like it is possible and Java reflection works for Scala as well, I just didn't read all answers for How to call a superclass method using Java reflection.
The following code works:
object TestApp {
def main(args: Array[String]) {
val a = new Successor;
val impl_lookup = classOf[MethodHandles.Lookup].getDeclaredField("IMPL_LOOKUP")
impl_lookup.setAccessible(true)
val lkp = impl_lookup.get(null).asInstanceOf[MethodHandles.Lookup];
val h1 = lkp.findSpecial(classOf[Base],
"name",
MethodType.methodType(classOf[String]),
classOf[Successor])
println(h1.invoke(a)) // prints "Base"
println(a.name) // prints "Successor"
}
}
Thanks to Jesse Glick for this solution.

Scala forward or delegate methods to encapsulated object

Is there any possibility to implicitly forward some of class methods to encapsulated object?
case class Entity(id: Int, name: String,) {
private lazy val lastScan = new LastScan
def getLastScanDate = lastScan.getLastScanDate
def updateLastScanDate = lastScan.updateLastScanDate
}
I want to avoid creating def updateLastScanDate = lastScan.updateLastScanDate just to forward methods to wrapped object.
In the plain language this is not possible. There used to be a compiler plugin by Kevin Wright to achieve this automatic delegation.
He seems to be working on an Autorproxy "Rebooted" version now that is macro based, making it straight forward to include in your project. I'm pasting here an example from its test sources:
trait Bippy {
def bippy(i : Int): String
}
object SimpleBippy extends Bippy {
def bippy(i: Int) = i.toString
}
#delegating class RawParamWrapper(#proxy pivot: Bippy)
val wrapper = new RawParamWrapper(SimpleBippy)
assert(wrapper.bippy(42) == "42")

Inject a dependency inside an object

I'm new to the Play framework and scala and I'm trying to inject a dependency inside a companion object.
I have a simple case class, like:
case class Bar(foo: Int) {}
With a companion object like:
object Bar {
val myDependency =
if (isTest) {
// Mock
}
else
{
// Actual implementation
}
val form = Form(mapping(
"foo" -> number(0, 100).verifying(foo => myDependency.validate(foo)),
)(Bar.apply)(Bar.unapply))
}
This works fine, but it's not really a clean way to do it. I'd like to be able to inject the dependency at build time so that I can inject different mock objects when testing and different real implementations in development and production.
What's the best way to achieve this?
Any help really appreciated. Thanks!
Along the lines of the Cake, we can try to change your example to
trait Validator {
def validate(foo: Int): Boolean
}
trait TestValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait ImplValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait BarBehavior {
def validator: Validator
val form = Form(mapping(...))(Bar.apply)(Bar.unapply)
}
//use this in your tests
object TestBar extends BarBehavior with TestValidation
//use this in production
object ImplBar extends BarBehavior with ImplValidation
You should additionally try and test if this example fits well within the Play Framework, too

Creating typed collection

II am trying to understand Scala collections by adding a new collection as follows:
class NewColl[V](values:Vector[V],someOtherParams)
extends IndexedSeq[V] with IndexedSeqLike[V, NewColl[V]] {
def fromSeq[V](seq: Seq[V]): NewColl[V] = ...
override def newBuilder[V]: Builder[V, NewColl[V]] =
new ArrayBuffer[V] mapResult fromSeq[V]
}
but I get the following error:
overriding method newBuilder in trait TraversableLike
of type => scala.collection.mutable.Builder[V,NewColl[V]];
method newBuilder in trait GenericTraversableTemplate
of type => scala.collection.mutable.Builder[V,IndexedSeq[V]] has incompatible type
Any Idea?
What I do in similar cases is to look at what the standard library does in similar cases. Looking at concrete subclasses of IndexedSeq they seem to mix in GenericTraversableTemplate. With that in mind, reworking your code to use it I get:
import collection.mutable._
import collection.generic.GenericTraversableTemplate
import collection.generic.GenericCompanion
class NewColl[V](values:Vector[V]) extends IndexedSeq[V] with
GenericTraversableTemplate[V, NewColl] {
def fromSeq[V](seq: Seq[V]): NewColl[V] = new NewColl(Vector(seq: _*))
override def companion: GenericCompanion[NewColl] = new GenericCompanion[NewColl]() {
def newBuilder[A]: Builder[A, NewColl[A]] = new Builder[A, NewColl[A]] {
val elems = new ArrayBuffer[A]()
def +=(a:A) = { elems += a; this }
def clear() { elems.clear }
def result(): NewColl[A] = fromSeq(elems)
}
}
}
(with someOtherParams removed for clarity)
Note that there are other questions on SO related to building classes on the scala 2.8 collection framework. For instance 5200505 which points to one of my favorite document The Architecture of Scala Collections. Also recently, Josh Suereth wrote a blog entry on creating your own collection class.