I have trimmed my code down to the following. I am confused why I am getting a stack overflow between the two filter methods (one in my trait and one in my superclass)
object TestingOutTraits {
val TestHandler = new Object with MySuper with MyTrait {
override lazy val createdFilter = {
"second part"
}
}
def main(args: Array[String]) = {
val result : String = TestHandler.start()
System.out.println("result="+result)
}
}
trait MySuper {
protected def filter: String = {
"first part to->"
}
def start() = {
filter
}
}
trait MyTrait { self: MySuper =>
lazy val createdFilter = {
"override this"
}
protected override def filter: String = {
self.filter + createdFilter
}
}
This is scala 2.9. Any ideas what is going on here?
EDIT:
The stack trace makes no sense on how it jumps back and forth too(I should have included it in original post)...
at MyTrait$class.filter(TestingOutTraits.scala:34)
at TestingOutTraits$$anon$1.filter(TestingOutTraits.scala:4)
at MyTrait$class.filter(TestingOutTraits.scala:34)
at TestingOutTraits$$anon$1.filter(TestingOutTraits.scala:4)
thanks,
Dean
The call self.filter in MyTrait.filter invokes itself, leading to infinite recursion that blows the stack.
Instead, have MyTrait extend MySuper, and use super.filter:
trait MyTrait extends MySuper {
lazy val createdFilter = {
"override this"
}
protected override def filter: String = {
super.filter + createdFilter
}
}
Alternatively,
trait MySuper extends Filtered {
protected def filter: String = {
"first part to->"
}
def start() = {
filter
}
}
trait Filtered {
protected def filter: String
}
trait MyTrait extends Filtered {
lazy val createdFilter = {
"override this"
}
protected abstract override def filter: String = {
super.filter + createdFilter
}
}
then
val nope = new MyTrait { } // correctly DNC
and the OP
val TestHandler = new MySuper with MyTrait {
override lazy val createdFilter = {
"second part"
}
}
http://www.artima.com/pins1ed/traits.html#12.5
Well, I know why the infinite recursion though this seems like a linearization bug in scala and I am not sure how to work around it yet either :(.
hmmmm, so it turns out the compiler is sticking a filter method in my new Object for some reason. I found this out with the print:mixin on scalac like so
$ scalac -Xprint:mixin TestingOutTraits.scala
[[syntax trees at end of mixin]]// Scala source: TestingOutTraits.scala
package <empty> {
final object TestingOutTraits extends java.lang.Object with ScalaObject {
private[this] val TestHandler: MySuper = _;
<stable> <accessor> def TestHandler(): MySuper = TestingOutTraits.this.TestHandler;
def main(args: Array[java.lang.String]): Unit = {
val result: java.lang.String = TestingOutTraits.this.TestHandler().start();
java.this.lang.System.out.println("result=".+(result))
};
def this(): object TestingOutTraits = {
TestingOutTraits.super.this();
TestingOutTraits.this.TestHandler = {
new anonymous class TestingOutTraits$$anon$1()
};
()
}
};
abstract trait MySuper extends java.lang.Object with ScalaObject {
def filter(): java.lang.String;
def start(): java.lang.String
};
abstract trait MyTrait extends java.lang.Object with ScalaObject { self: MyTrait =>
def createdFilter(): java.lang.String;
override def filter(): java.lang.String
};
abstract trait MySuper$class extends {
def filter($this: MySuper): java.lang.String = "first part to->";
def start($this: MySuper): java.lang.String = $this.filter();
def /*MySuper$class*/$init$($this: MySuper): Unit = {
()
}
};
abstract trait MyTrait$class extends { self: MyTrait =>
def createdFilter($this: MyTrait): java.lang.String = "override this";
override def filter($this: MyTrait): java.lang.String = $this.$asInstanceOf[MySuper]().filter().+($this.createdFilter());
def /*MyTrait$class*/$init$($this: MyTrait): Unit = {
()
}
};
final class TestingOutTraits$$anon$1 extends java.lang.Object with MySuper with MyTrait {
override def filter(): java.lang.String = MyTrait$class.filter(TestingOutTraits$$anon$1.this);
def start(): java.lang.String = MySuper$class.start(TestingOutTraits$$anon$1.this);
override def createdFilter(): java.lang.String = "second part";
def this(): anonymous class TestingOutTraits$$anon$1 = {
TestingOutTraits$$anon$1.super.this();
MySuper$class./*MySuper$class*/$init$(TestingOutTraits$$anon$1.this);
MyTrait$class./*MyTrait$class*/$init$(TestingOutTraits$$anon$1.this);
()
}
}
Related
I am trying to build a DSL, one of the method on this DSL is parameterless and use a bounded generic type. Today I have to add a "feature" that will ideally use the same method name. However, because the only parameter is the generic one, I cannot override it with the usual way.
Is there a trick to allow the use of the same method for different generic types ?
My method looks like:
def ask[H <: Handler] = {
new CommandBuilder[H]
}
class CommandBuilder[H <: Handler] {
def toExecute[C <: H#C](command: C) = {
//...
}
}
And I would like to add:
def ask[S <: State] = {
new QueryBuilder[S]
}
class QueryBuilder[S <: State] {
def toExecute[Q <: S#Q](query: Q) = {
//...
}
}
I was thinking to pattern match a ClassTag on the type but I need strong type safety:
Query on a Handler, is not allowed. ask[State] must return QueryBuilder
Command and Query are the only supported types. The generic type of ask can only be a Handler or a State.
Maybe you could refactor your code to something like this?
sealed trait FooBar
sealed trait Foo extends FooBar {
def process(i: Int): Int
}
object Foo {
implicit final case object FooImpl extends Foo {
override def process(i: Int): Int = i + 1
}
}
sealed trait Bar extends FooBar {
def process(s: String): String
}
object Bar {
implicit final case object BarImpl extends Bar {
override def process(s: String): String = s.toUpperCase
}
}
object Test {
trait FooBarPartiallyApplied[FB <: FooBar] {
type Out
def out: Out
}
object FooBarPartiallyApplied {
type Aux[FB <: FooBar, _Out] = FooBarPartiallyApplied[FB] { type Out = _Out }
implicit final def FooPartiallyAppliedBuilder[F <: Foo]: Aux[F, FooPartiallyApplied[F]] =
new FooBarPartiallyApplied[F] {
override final type Out = FooPartiallyApplied[F]
override final val out: FooPartiallyApplied[F] =
new FooPartiallyApplied[F](dummy = true)
}
implicit final def BarPartiallyAppliedBuilder[B <: Bar]: Aux[B, BarPartiallyApplied[B]] =
new FooBarPartiallyApplied[B] {
override final type Out = BarPartiallyApplied[B]
override final val out: BarPartiallyApplied[B] =
new BarPartiallyApplied[B](dummy = true)
}
final class FooPartiallyApplied[F <: Foo](private val dummy: Boolean) extends AnyVal {
def toExecute(i: Int)(implicit foo: F): Int = foo.process(i)
}
final class BarPartiallyApplied[B <: Bar](private val dummy: Boolean) extends AnyVal {
def toExecute(s: String)(implicit bar: B): String = bar.process(s)
}
}
def ask[FB <: FooBar](implicit pa: FooBarPartiallyApplied[FB]): pa.Out =
pa.out
}
It works as expected:
Test.ask[Foo.FooImpl.type].toExecute(10)
// res: Int = 11
Test.ask[Foo.FooImpl.type].toExecute("blah")
// Type error.
Test.ask[Bar.BarImpl.type].toExecute(10)
// Type error.
Test.ask[Bar.BarImpl.type].toExecute("blah")
// res: String = "BLAH"
Suppose I have a trait defined like
trait SomeTrait[A] {
def doSomething(): Seq[A]
}
and multiple classes that extend this trait as follows.
class SomeClass extends SomeTrait[SomeType] {
def doSomething(): Seq[SomeType] = {
:
}
}
Now in another class, I want to store the collection of instances of the classes extending the trait.
class AnotherClass {
pirvate val someClassInstances = mutable.Buffer[SomeTrait[_]]()
def addSomeClass[A](sc: SomeTrait[A]): Unit = {
this.someClassInstances += sc
}
}
How can I avoid using the existential type here?
Does the following meet your needs:
import scala.collection.mutable
trait SomeTrait[A] {
def doSomething(): Seq[A]
}
class SomeClass extends SomeTrait[Int] {
def doSomething(): Seq[Int] = ???
}
class AnotherClass {
private val someClassInstances = mutable.Buffer[SomeTrait[_]]()
def addSomeClass(sc: SomeTrait[_]): Unit = {
this.someClassInstances += sc
}
}
?
Consider this trait:
trait Foo {
def m1(id : Int) : Try[String]
}
And an instance of this:
val g : Foo = new Foo {
override def m1(id: Int): Try[String] = Success("Good job")
}
Intellij offered a suggestion that this could converted to a Single Abstract Method:
val g : Foo = (id: Int) => Success("Good job")
Are these two equivalent and how?
Lets check what the scalac do for:
import scala.util.{Success, Try}
trait Foo {
def m1(id : Int) : Try[String]
}
object MainClass {
val g : Foo = new Foo {
override def m1(id: Int): Try[String] = Success("Good job")
}
}
run:
$ scalac -print src/main/scala/MainClass.scala
and output:
[[syntax trees at end of cleanup]] // MainClass.scala
package <empty> {
abstract trait Foo extends Object {
def m1(id: Int): scala.util.Try
};
object MainClass extends Object {
private[this] val g: Foo = _;
<stable> <accessor> def g(): Foo = MainClass.this.g;
def <init>(): MainClass.type = {
MainClass.super.<init>();
MainClass.this.g = {
new <$anon: Foo>()
};
()
}
};
final class anon$1 extends Object with Foo {
override def m1(id: Int): scala.util.Try = new scala.util.Success("Good job");
def <init>(): <$anon: Foo> = {
anon$1.super.<init>();
()
}
}
}
And do the same steps for:
import scala.util.{Success, Try}
trait Foo {
def m1(id : Int) : Try[String]
}
object MainClass {
def main(args: Array[String]): Unit = {
val g : Foo = (id: Int) => Success("Good job")
}
}
run:
$ scalac -print src/main/scala/MainClass.scala
output:
[[syntax trees at end of cleanup]] // MainClass.scala
package <empty> {
abstract trait Foo extends Object {
def m1(id: Int): scala.util.Try
};
object MainClass extends Object {
private[this] val g: Foo = _;
<stable> <accessor> def g(): Foo = MainClass.this.g;
final <artifact> private[this] def $anonfun$g$1(id: Int): scala.util.Try = new scala.util.Success("Good job");
def <init>(): MainClass.type = {
MainClass.super.<init>();
MainClass.this.g = {
((id: Int) => MainClass.this.$anonfun$g$1(id))
};
()
}
}
}
As you can see they are not the same for compiler.
In the first case, it is an anonymous object in second it is an anonymous function.
I am trying to implement a cake pattern like code, but I get:
Error:(47, 36) illegal inheritance;
self-type app.server.im.Im_Api_Service_Impl.type does not conform to app.server.im.Persistence[app.server.im.State.State]'s selftype app.server.im.Persistence[app.server.im.State.State] with app.server.im.Persistable[app.server.im.State.State]
object Im_Api_Service_Impl extends Persistence[State.State]
with the code below.
What might be the problem ?
I looked at this SOF question, but it seems to describe a different scenerio (or maybe I am just not seeing the similarity).
import app.shared.IndexChange
import app.shared.apiAndModel.im.{CanCreateEntity, Im_Api_Interface, LineShared, LineSharedPayload, UUID}
import upickle.default._
object State {
type State = Seq[LineShared]
}
trait Im_Api_Service extends Im_Api_Interface with Persistable[State.State] {
implicit object CanCreate extends CanCreateEntity
import State.State
val init = List("egy", "ketto", "harom", "negy", "ot", "hat", "het", "nyolc").map(LineSharedPayload(_)).map(LineShared(_))
val fileNameForPersistence="state"
var state: State = init
def setState(s:State)={state=s}
override def getLines(): Seq[LineShared] = state
def moveLine(ls: State, from: Int, to: Int): Seq[LineShared] = {
val r=IndexChange(from, to).updatedList[LineShared](ls.toList)
r
}
override def moveLine(from: Int, to: Int): Seq[LineShared] = {state=moveLine(state, from, to);state;}
override def newLine(pl: LineSharedPayload): Seq[LineShared] = {
setState(state :+ LineShared(pl))
state
}
def getLine(ls:State, id: UUID): Option[LineShared] = ls.find(_.id == id)
override def getLine(id: UUID): Option[LineShared] = getLine(state,id)
override def updateLine(l: LineShared): State = {
setState(state.map(ll => if (ll~l) l else ll ))
state
}
}
object Im_Api_Service_Impl extends Persistence[State.State]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
illegal inheritance problem HERE
trait Persistable[State]
{
val fileNameForPersistence:String
var state :State
}
trait Persistence[State] { this:Persistable[State] =>
def serializeState(s: State): String = write(s)
// TODO add timestamp to filename
def saveState(): Unit = writeToFile(serializeState(state), fileNameForPersistence)
def loadState(): Unit = {
try {
state = deserializeState(readFromFile(fileNameForPersistence))
}
catch {
case e: Exception => println(e)
}
}
def writeToFile(s: String, fn: String): Unit = {
import java.io._
val pw = new PrintWriter(new File(fn))
pw.write(s)
pw.close
}
def readFromFile(fn: String): String = {
val source = scala.io.Source.fromFile(fn)
val lines: String = try source.mkString finally source.close()
lines
}
def deserializeState(s: String): State = read[State](s)
}
You have promised that trait Persistence would only be mixed into a class that extends Persistable: trait Persistence[State] { this:Persistable[State].
Instead, your object extends Persistence[State.State]. Is that the same thing?
Is this an intended behavior or is it a bug? Consider the following trait (be it a class, doesn't matter):
trait P[T] {
class Inner(val f: T => Unit = _ => println("nope"))
}
This is what I would have expected:
scala> val p = new P[Int] {
| val inner = new Inner
| }
p: java.lang.Object with P[Int]{def inner: this.Inner} = $anon$1#12192a9
scala> p.inner.f(5)
nope
But this?
scala> val p = new P[Int] {
| val inner = new Inner() {
| println("some primary constructor code in here")
| }
| }
<console>:6: error: type mismatch;
found : (T) => Unit
required: (Int) => Unit
val inner = new Inner() {
^
That appears to be a bug, albeit at a rather obscure intersection between nested classes, abstract types, and default parameters. You could raise a ticket in the Scala bug tracker -- I couldn't find an existing ticket describing this.
Here's how it looks after the typer phase:
~: scala -nocompdaemon -Xprint:typer -e 'trait P[T] { class Inner(val f: T = null.asInstanceOf[T]) }; new P[Int] { new Inner(){} }'
!!!
discarding <script preamble>
(fragment of scalacmd162105603941759154.scala):1: error: type mismatch;
found : T
required: Int
trait P[T] { class Inner(val f: T = null.asInstanceOf[T]) }; new P[Int] { new Inner(){} }
^
[[syntax trees at end of typer]]// Scala source: (virtual file)
package <empty> {
final object Main extends java.lang.Object with ScalaObject {
def this(): object Main = {
Main.super.this();
()
};
def main(argv: Array[String]): Unit = {
val args: Array[String] = argv;
{
final class $anon extends scala.AnyRef {
def this(): anonymous class $anon = {
$anon.super.this();
()
};
abstract trait P[T >: Nothing <: Any] extends java.lang.Object with ScalaObject {
def /*P*/$init$(): Unit = {
()
};
class Inner extends java.lang.Object with ScalaObject {
<paramaccessor> private[this] val f: T = _;
<stable> <accessor> <paramaccessor> def f: T = Inner.this.f;
def this(f: T = null.asInstanceOf[T]): P.this.Inner = {
Inner.super.this();
()
}
};
final <synthetic> object Inner extends java.lang.Object with ScalaObject {
<synthetic> def init$default$1: T #scala.annotation.unchecked.uncheckedVariance = null.asInstanceOf[T];
def this(): object P.this.Inner = {
Inner.super.this();
()
}
}
};
{
final class $anon extends java.lang.Object with this.P[Int] {
def this(): anonymous class $anon = {
$anon.super.this();
()
};
{
final class $anon extends $anon.this.Inner {
def this(): anonymous class $anon = {
$anon.super.this(P.this.Inner.<error: method init$default$1>);
()
};
<empty>
};
new $anon()
}
};
new $anon()
}
};
{
new $anon();
()
}
}
}
}
}
And the working version, without the anonymous inner class extending Inner.
~: scala -nocompdaemon -Xprint:typer -e 'trait P[T] { class Inner(val f: T = null.asInstanceOf[T]) }; new P[Int] { new Inner() }'
[[syntax trees at end of typer]]// Scala source: (virtual file)
package <empty> {
final object Main extends java.lang.Object with ScalaObject {
def this(): object Main = {
Main.super.this();
()
};
def main(argv: Array[String]): Unit = {
val args: Array[String] = argv;
{
final class $anon extends scala.AnyRef {
def this(): anonymous class $anon = {
$anon.super.this();
()
};
abstract trait P[T >: Nothing <: Any] extends java.lang.Object with ScalaObject {
def /*P*/$init$(): Unit = {
()
};
class Inner extends java.lang.Object with ScalaObject {
<paramaccessor> private[this] val f: T = _;
<stable> <accessor> <paramaccessor> def f: T = Inner.this.f;
def this(f: T = null.asInstanceOf[T]): P.this.Inner = {
Inner.super.this();
()
}
};
final <synthetic> object Inner extends java.lang.Object with ScalaObject {
<synthetic> def init$default$1: T #scala.annotation.unchecked.uncheckedVariance = null.asInstanceOf[T];
def this(): object P.this.Inner = {
Inner.super.this();
()
}
}
};
{
final class $anon extends java.lang.Object with this.P[Int] {
def this(): anonymous class $anon = {
$anon.super.this();
()
};
new $anon.this.Inner($anon.this.Inner.init$default$1)
};
new $anon()
}
};
{
new $anon();
()
}
}
}
}
}