Forwarding calls to underlying object in Scala - scala

I have the following class definition:
class Foo[T](iteratorThunk: () => Iterator[T]) {
def values = iteratorThunk()
}
And I would like Foo to have all the methods that Iterator exposes, while still returning objects of type Foo. For instance, I would like to be able to do:
val a = new Foo({ () => List(1, 2, 3).toIterator })
val b = new Foo({ () => List(4, 5, 6).toIterator })
val c = a ++ b
And have c equal to:
new Foo({ () => a.values ++ b.values })
I had a look at forwarders (IterableForwarder, TraversableForwarder, ...), but none seemed fit to forward methods to an Iterator, and I would still like to keep Foo as both the static and dynamic result type.
What is the best way to achieve this behavior, without defining every forwarding method?

I need the Foo class as it is, and not only as an Iterator because I
need to be able to do more than one pass through its values.
Then you want either a Traverable or an Iterable. To have them work as you wish, you need to extend both them and TraversableLike or IterableLike, through which you'll specify the return type. And you'll need to provide both a Builder and a CanBuildFrom as well.
Here's a simple implementation:
import scala.collection.IterableLike
import scala.collection.mutable.LazyBuilder
class Foo[T](iteratorThunk: () => Iterator[T]) extends Iterable[T] with IterableLike[T, Foo[T]] {
def iterator = iteratorThunk()
override protected def newBuilder = new Foo.FooBuilder[T]
}
object Foo {
class FooBuilder[T] extends LazyBuilder[T, Foo[T]] {
def result(): Foo[T] = {
val coll = parts.toList.flatten
new Foo(() => coll.iterator)
}
}
}

Related

Pass Scala.js class instance to JavaScript that will invoke the function call method

I have a simple Scala.js class (Scala-2.12.10 and Scala-js 0.6.31):
class Foo extends js.Object {
def apply() = { println("apply") }
def bar() = { println("bar") }
}
val myfoo = new Foo()
An instance of Foo will be passed to a JavaScript library which will in turn attempt to invoke the following two methods:
myfoo()
myfoo.bar()
Of course, this will not work because I cannot define the apply method on Foo since it derives from js.Object and that will not translate to calling () on the object.
How does one construct an appropriate class for this scenario?
Update:
Here is some example code based on #sjrd's answer that provides for strong typing while encapsulating the js.Dynamic complexity.
trait FooTrait extends js.Object {
def own()
def bar()
}
class Foo extends FooTrait {
def own() = { println("apply") }
def bar() = { println("bar") }
}
def makeFoo(foo: FooTrait]) = {
val jsFoo = ({ () =>
foo.own()
}: js.Function0[Unit]).asInstanceOf[js.Dynamic]
jsFoo.bar = ({ () =>
foo.bar()
}: js.Function0[Unit])
jsFoo
}
val myFoo = makeFoo(new Foo())
Now myFoo is ready to be passed to the JavaScript library.
In JavaScript, the only way that a call like myfoo() can be valid is if myfoo was created as a function value. To make myfoo.bar() work in addition, that must be patched on the function value after it's created. There is no way (except proxies, which are another beast entirely) to create myfoo as an object first, from a class or not, and make it answer to myfoo().
Therefore, this is also what you have to do in Scala.js:
val myfoo = ({ () =>
println("apply")
}: js.Function0[Unit]).asInstanceOf[js.Dynamic]
myfoo.bar = ({ () =>
println("bar")
}: js.Function0[Unit])
After that, you can pass myfoo to the JavaScript code.

Creating instance type after filter

I have a simple class which extends IndexedSeq[MyType]
class MyClass(someName: String, values: Iterable[MyType]) extends IndexedSeq[MyType] {
val name = someName
val rows = values.toVector
....
}
This works fine, allowing me to call all the standard collection methods on this object, filter, map etc and returning me the results as an IndexedSeq[MyType].
What I would like is for the results be returned as a new instance of MyClass or a boilerplate free way of doing this so I don't require the additional manual step each time of creating a new MyClass. EG:
val results = myClassInstance.filter(t => t)
val newMyClass = new MyClass(myClassInstance.name, results)
Is there any way of simplifying and doing something like the following, given that I need access to the original myClassInstance to copy the name value from it to the new object.
val newMyClass = myClassInstance.filter(t => t).toMyClass
Thanks
I've figured out the solution by extending IndexedSeqLike[DataRow, DataView] and implementing a builder in the companion object. So far this seems to do exactly what I was after without needing passthough calls.
class MyClass(someName: String, values: Iterable[MyType])
extends IndexedSeq[MyType]
with IndexedSeqLike[MyType, MyClass] {
val name = someName
val rows = values.toVector
// Supply a builder method which will get used on filter, reverse etc,
override def newBuilder: mutable.Builder[MyType, MyClass] =
MyClass.newBuilder(name)
....
}
Then in the companion object, add the following...
object MyClass {
// Builder for a new MyClass instance.
def newBuilder(name: String): mutable.Builder[MyType, MyClass] =
Vector.newBuilder[MyType] mapResult (vector => new MyClass(name, vector))
}
Now the following work as required :
val filteredData: MyClass = myClass.filter(f => f)
val reversedData: MyClass = myClass.reverse
Are you sure you need to inherit from IndexedSeq?
If you need only filter & map function in your class, you can implement them, without overriding IndexedSeq
class MyClass(name: String, values: Iterable[MyType]) {
def filter(f: MyType => Boolean): MyClass = {
new MyClass(name, values.filter(f))
}
def map(f: MyType => MyType): MyClass = {
new MyClass(name, values.map(f))
}
}
or If you really really need to override IndexedSeq, you can add explicit filter method to your class
class MyClass(name: String, values: Iterable[MyType]) extends IndexedSeq[MyClass] {
def filterClass(f: MyType => Boolean): MyClass = {
new MyClass(name, values.filter(f))
}
}
Or another option
class MyClass(name: String, values: Iterable[MyType]) extends IndexedSeq[MyClass] {
def copyWith(f: Iterable[MyType] => Iterable[MyType]): MyClass = {
new MyClass(name, f(values))
}
}
MyClass.copyWith(_.filter(...))
MyClass.copyWith(_.filterNot(...))
MyClass.copyWith(_.map(...))

Scala case class prohibits call-by-name parameters?

Scenario:
I want to implement an infinite list:
abstract class MyList[+T]
case object MyNil extends MyList[Nothing]
case class MyNode[T](h:T,t: => MyList[T]) extends MyList[T]
//error: `val' parameters may not be call-by-name
Problem:
The error is that call-by-name is not allowed.
I've heard that it is because val or var constructor parameter is not allowed for call-by-name. For example:
class A(val x: =>Int)
//error: `val' parameters may not be call-by-name
But in contrast the normal constructor parameter is still val, despite private. For example:
class A(x: =>Int)
// pass
So the Question :
Is the problem really about val or var ?
If that, since the point for call-by-name is to defer computation. Why could not val or var computation(or initialization) be deferred?
How to get around the case class limitation to implement an infinite list?
There is no contradiction: class A(x: => Int) is equivalent to class A(private[this] val x: => Int) and not class A(private val x: => Int). private[this] marks a value instance-private, while a private-modifier without further specification allows accessing the value from any instance of that class.
Unfortunately, defining a case class A(private[this] val x: => Int) is not allowed either. I assume it is because case-classes need access to the constructor values of other instances, because they implement the equals method.
Nevertheless, you could implement the features that a case class would provide manually:
abstract class MyList[+T]
class MyNode[T](val h: T, t: => MyList[T]) extends MyList[T]{
def getT = t // we need to be able to access t
/* EDIT: Actually, this will also lead to an infinite recursion
override def equals(other: Any): Boolean = other match{
case MyNode(i, y) if (getT == y) && (h == i) => true
case _ => false
}*/
override def hashCode = h.hashCode
override def toString = "MyNode[" + h + "]"
}
object MyNode {
def apply[T](h: T, t: => MyList[T]) = new MyNode(h, t)
def unapply[T](n: MyNode[T]) = Some(n.h -> n.getT)
}
To check this code, you could try:
def main(args: Array[String]): Unit = {
lazy val first: MyNode[String] = MyNode("hello", second)
lazy val second: MyNode[String] = MyNode("world", first)
println(first)
println(second)
first match {
case MyNode("hello", s) => println("the second node is " + s)
case _ => println("false")
}
}
Unfortunately, I do not know for sure why call-by-name val and var members are prohibited. However, there is at least one danger to it: Think about how case-classes implement toString; The toString-method of every constructor value is called. This could (and in this example would) lead to the values calling themselves infinitely. You can check this by adding t.toString to MyNode's toString-method.
Edit: After reading Chris Martin's comment: The implementation of equals will also pose a problem that is probably more severe than the implementation of toString (which is mostly used for debugging) and hashCode (which will only lead to higher collision rates if you can't take the parameter into account). You have to think carefully about how you would implement equals to be meaningfull.
I have also not found why exactly by-name parameters are prohibited in case classes. I guess explanation should be quite elaborate and complex.
But Runar Bjarnason in his book "Functional Programming in Scala" provides a good approach to handle this obstacle. He uses the concept of a "thunk" together with memoizing.
Here is an example of Stream implementation:
sealed trait Stream[+A]
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
object Stream {
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
def empty[A]: Stream[A] = Empty
def apply[A](as: A*): Stream[A] =
if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
}
}
As you see, instead of a regular by-name parameter for the case class data constructor they use what they call a "thunk", a function of zero-arguments () => T. Then to make this transparent for the user they declare a smart constructor in the companion object which allows you to provide a by-name parameters and make them memoized.
This is actually similar approach to the Stream solution but simplified to what is actually required:
case class A(x: () => Int) {
lazy val xx = x()
}
So you can use your case class as:
def heavyOperation: Int = ???
val myA = A(heavyOperation)
val myOtherA = A(() => 10)
val useA = myA.xx + myOtherA.xx
Like this the actual heavy operation will be performed only when you use xx, i.e., only on the last line.
I like using an implicit function to make a thunk work like a call by name.
e.g. in this example:
case class Timed[R](protected val block: () => R) {
override def toString() = s"Elapsed time: $elapsedTime"
val t0 = System.nanoTime()
val result = block() // execute thunk
val t1 = System.nanoTime()
val elapsedTime = t1 - t0
}
implicit def blockToThunk[R](bl: => R) = () => bl //helps to call Timed without the thunk syntax
this let's you call Timed({Thread.sleep(1000); println("hello")}) for example with call by name syntax

A case class as a "wrapper" class for a collection. What about map/foldLeft/

What I try to do is to come up with a case class which I can use in pattern matching which has exactly one field, e.g. an immutable set. Furthermore, I would like to make use of functions like map, foldLeft and so on which should be passed down to the set. I tried it as in the following:
case class foo(s:Set[String]) extends Iterable[String] {
override def iterator = s.iterator
}
Now if I try to make use of e.g. the map function, I get an type error:
var bar = foo(Set() + "test1" + "test2")
bar = bar.map(x => x)
found : Iterable[String]
required: foo
bar = bar.map(x => x)
^
The type error is perfectly fine (in my understanding). However, I wonder how one would implement a wrapper case class for a collection such that one can call map, foldLeft and so on and still receive an object of the case class. Would one need to override all these functions or is there some other way around?
Edit
I'm inclined to accept the solution of RĂ©gis Jean-Gilles which works for me. However, after Googling for hours I found another interesting Scala trait named SetProxy. I couldn't find any trivial examples so I'm not sure if this trait does what I want:
come up with a custom type, i.e. a different type than Set
the type must be a case class (we want to do pattern matching)
we need "delegate" methods map, foldLeft and so on which should pass the call to our actual set and return the resulting set wrapped arround in our new type
My first idea was to extend Set but my custom type Foo already extends another class. Therefore, the second idea was to mixin the trait Iterable and IterableLike. Now I red about the trait SetProxy which made me think about which is "the best" way to go. What are your thoughts and experiences?
Since I started learning Scala three days ago, any pointers are highly appreciated!
Hmm this sounds promissing to me but Scala says that variable b is of type Iterable[String] and not of type Foo, i.e. I do not see how IterableLike helps in this situation
You are right. Merely inheriting from IterableLike as shown by mpartel will make the return type of some methods more precise (such as filter, which will return Foo), but for others such as map of flatMap you will need to provide an appopriate CanBuildFrom implicit.
Here is a code snippet that does just that:
import collection.IterableLike
import collection.generic.CanBuildFrom
import collection.mutable.Builder
case class Foo( s:Set[String] ) extends Iterable[String] with IterableLike[String, Foo] {
override def iterator = s.iterator
override protected[this] def newBuilder: scala.collection.mutable.Builder[String, Foo] = new Foo.FooBuilder
def +(elem: String ): Foo = new Foo( s + elem )
}
object Foo {
val empty: Foo = Foo( Set.empty[String] )
def apply( elems: String* ) = new Foo( elems.toSet )
class FooBuilder extends Builder[String, Foo] {
protected var elems: Foo = empty
def +=(x: String): this.type = { elems = elems + x; this }
def clear() { elems = empty }
def result: Foo = elems
}
implicit def canBuildFrom[T]: CanBuildFrom[Foo, String, Foo] = new CanBuildFrom[Foo, String, Foo] {
def apply(from: Foo) = apply()
def apply() = new FooBuilder
}
}
And some test in the repl:
scala> var bar = Foo(Set() + "test1" + "test2")
bar: Foo = (test1, test2)
scala> bar = bar.map(x => x) // compiles just fine because map now returns Foo
bar: Foo = (test1, test2)
Inheriting IterableLike[String, Foo] gives you all those methods such that they return Foo. IterableLike requires you to implement newBuilder in addition to iterator.
import scala.collection.IterableLike
import scala.collection.mutable.{Builder, SetBuilder}
case class Foo(stuff: Set[String]) extends Iterable[String] with IterableLike[String, Foo] {
def iterator: Iterator[String] = stuff.iterator
protected[this] override def newBuilder: Builder[String, Foo] = {
new SetBuilder[String, Set[String]](Set.empty).mapResult(Foo(_))
}
}
// Test:
val a = Foo(Set("a", "b", "c"))
val b = a.map(_.toUpperCase)
println(b.toList.sorted.mkString(", ")) // Prints A, B, C

Automatically Hash Consed Case Classes

I'm looking for a way to have classes that behave just like case classes, but that are automatically hash consed.
One way to achieve this for integer lists would be:
import scala.collection.mutable.{Map=>MutableMap}
sealed abstract class List
class Cons(val head: Int, val tail: List) extends List
case object Nil extends List
object Cons {
val cache : MutableMap[(Int,List),Cons] = MutableMap.empty
def apply(head : Int, tail : List) = cache.getOrElse((head,tail), {
val newCons = new Cons(head, tail)
cache((head,tail)) = newCons
newCons
})
def unapply(lst : List) : Option[(Int,List)] = {
if (lst != null && lst.isInstanceOf[Cons]) {
val asCons = lst.asInstanceOf[Cons]
Some((asCons.head, asCons.tail))
} else None
}
}
And, for instance, while
scala> (5 :: 4 :: scala.Nil) eq (5 :: 4 :: scala.Nil)
resN: Boolean = false
we get
scala> Cons(5, Cons(4, Nil)) eq Cons(5, Cons(4, Nil))
resN: Boolean = true
Now what I'm looking for is a generic way to achieve this (or something very similar). Ideally, I don't want to have to type much more than:
class Cons(val head : Int, val tail : List) extends List with HashConsed2[Int,List]
(or similar). Can someone come up with some type system voodoo to help me, or will I have to wait for the macro language to be available?
You can define a few InternableN[Arg1, Arg2, ..., ResultType] traits for N being the number of arguments to apply(): Internable1[A,Z], Internable2[A,B,Z], etc. These traits define the cache itself, the intern() method and the apply method we want to hijack.
We'll have to define a trait (or an abstract class) to assure your InternableN traits that there is indeed an apply method to be overriden, let's call it Applyable.
trait Applyable1[A, Z] {
def apply(a: A): Z
}
trait Internable1[A, Z] extends Applyable1[A, Z] {
private[this] val cache = WeakHashMap[(A), Z]()
private[this] def intern(args: (A))(builder: => Z) = {
cache.getOrElse(args, {
val newObj = builder
cache(args) = newObj
newObj
})
}
abstract override def apply(arg: A) = {
println("Internable1: hijacking apply")
intern(arg) { super.apply(arg) }
}
}
The companion object of your class will have to be a mixin of a concrete class implementing ApplyableN with InternableN. It would not work to have apply directly defined in your companion object.
// class with one apply arg
abstract class SomeClassCompanion extends Applyable1[Int, SomeClass] {
def apply(value: Int): SomeClass = {
println("original apply")
new SomeClass(value)
}
}
class SomeClass(val value: Int)
object SomeClass extends SomeClassCompanion with Internable1[Int, SomeClass]
One good thing about this is that the original apply need not be modified to cater for interning. It only creates instances and is only called when they need to be created.
The whole thing can (and should) also be defined for classes with more than one argument. For the two-argument case:
trait Applyable2[A, B, Z] {
def apply(a: A, b: B): Z
}
trait Internable2[A, B, Z] extends Applyable2[A, B, Z] {
private[this] val cache = WeakHashMap[(A, B), Z]()
private[this] def intern(args: (A, B))(builder: => Z) = {
cache.getOrElse(args, {
val newObj = builder
cache(args) = newObj
newObj
})
}
abstract override def apply(a: A, b: B) = {
println("Internable2: hijacking apply")
intern((a, b)) { super.apply(a, b) }
}
}
// class with two apply arg
abstract class AnotherClassCompanion extends Applyable2[String, String, AnotherClass] {
def apply(one: String, two: String): AnotherClass = {
println("original apply")
new AnotherClass(one, two)
}
}
class AnotherClass(val one: String, val two: String)
object AnotherClass extends AnotherClassCompanion with Internable2[String, String, AnotherClass]
The interaction shows that the Internables' apply method executes prior to the original apply() which gets executed only if needed.
scala> import SomeClass._
import SomeClass._
scala> SomeClass(1)
Internable1: hijacking apply
original apply
res0: SomeClass = SomeClass#2e239525
scala> import AnotherClass._
import AnotherClass._
scala> AnotherClass("earthling", "greetings")
Internable2: hijacking apply
original apply
res1: AnotherClass = AnotherClass#329b5c95
scala> AnotherClass("earthling", "greetings")
Internable2: hijacking apply
res2: AnotherClass = AnotherClass#329b5c95
I chose to use a WeakHashMap so that the interning cache does not prevent garbage collection of interned instances once they're no longer referenced elsewhere.
Code neatly available as a Github gist.
Maybe a little hacky, but you could try defining your own intern() method, like Java's String has:
import scala.collection.mutable.{Map=>MutableMap}
object HashConsed {
val cache: MutableMap[(Class[_],Int), HashConsed] = MutableMap.empty
}
trait HashConsed {
def intern(): HashConsed =
HashConsed.cache.getOrElse((getClass, hashCode), {
HashConsed.cache((getClass, hashCode)) = this
this
})
}
case class Foo(bar: Int, baz: String) extends HashConsed
val foo1 = Foo(1, "one").intern()
val foo2 = Foo(1, "one").intern()
println(foo1 == foo2) // true
println(foo1 eq foo2) // true