Problem with traits

View: New views
6 Messages — Rating Filter:   Alert me  

Problem with traits

by Albert Strasheim :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello all

I'm having a problem with traits that I would appreciate some help with:

I have the following two classes, each with a ! method:

class Foo {
  def !(message: Any) = println("foo: " + message)
}

class Baz {
  def !(message: Any) = println("baz: " + message)
}

First, a trait with a self-type only for Foo:

trait Bar {
  self: Foo =>
    def bang(message: Any) = {
      self ! message
    }
}

This compiles without problems and works fine. But if I do:

trait Bar2 {
  self =>
    def bang(message: Any) = {
      self ! message
    }
}

I get the following compiler error:

error: value ! is not a member of Bar2

The rest of the code:

object TraitStuff {
  def main(args : Array[String]) {
    val foo = new Foo with Bar
    val baz = new Baz with Bar2
    foo.bang("bar")
    baz.bang("bar")
  }
}

I'm using scala-2.8.0.r19180-b20091021023451. Any help would be appreciated.

Regards,

Albert

RE: Problem with traits

by Detering Dirk-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> I'm having a problem with traits that I would appreciate some
> help with:
>
> I have the following two classes, each with a ! method:
>
> class Foo {
>   def !(message: Any) = println("foo: " + message) }
>
> class Baz {
>   def !(message: Any) = println("baz: " + message) }
>
> First, a trait with a self-type only for Foo:
>
> trait Bar {
>   self: Foo =>
>     def bang(message: Any) = {
>       self ! message
>     }
> }
>
> This compiles without problems and works fine. But if I do:
>
> trait Bar2 {
>   self =>

Is it intentionally that you left out the
specific type here?
(You declared it in Bar with self: Foo =>,
but not here in Bar2)



>     def bang(message: Any) = {
>       self ! message
>     }
> }
>
> I get the following compiler error:
>
> error: value ! is not a member of Bar2
>
> The rest of the code:
>
> object TraitStuff {
>   def main(args : Array[String]) {
>     val foo = new Foo with Bar
>     val baz = new Baz with Bar2
>     foo.bang("bar")
>     baz.bang("bar")
>   }
> }
>
> I'm using scala-2.8.0.r19180-b20091021023451. Any help would
> be appreciated.
>
> Regards,
>
> Albert
> --
> View this message in context:
> http://old.nabble.com/Problem-with-traits-tp26157101p26157101.html
> Sent from the Scala - User mailing list archive at Nabble.com.
>
>

Re: Problem with traits

by Albert Strasheim :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello all

On Mon, Nov 2, 2009 at 5:33 PM, Detering Dirk <Dirk.Detering@...> wrote:

>> trait Bar {
>>   self: Foo =>
>>     def bang(message: Any) = {
>>       self ! message
>>     }
>> }
>> This compiles without problems and works fine. But if I do:
>>
>> trait Bar2 {
>>   self =>
> Is it intentionally that you left out the
> specific type here?
> (You declared it in Bar with self: Foo =>,
> but not here in Bar2)
>>     def bang(message: Any) = {
>>       self ! message
>>     }
>> }
>> I get the following compiler error:
>> error: value ! is not a member of Bar2

Yes, it's intentional. I am trying to make a trait that works for any
class that has a ! method.

Regards,

Albert

Re: Problem with traits

by David Hall-17 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Nov 2, 2009 at 10:28 PM, Albert Strasheim <fullung@...> wrote:

> Hello all
>
> On Mon, Nov 2, 2009 at 5:33 PM, Detering Dirk <Dirk.Detering@...> wrote:
>>> trait Bar {
>>>   self: Foo =>
>>>     def bang(message: Any) = {
>>>       self ! message
>>>     }
>>> }
>>> This compiles without problems and works fine. But if I do:
>>>
>>> trait Bar2 {
>>>   self =>
>> Is it intentionally that you left out the
>> specific type here?
>> (You declared it in Bar with self: Foo =>,
>> but not here in Bar2)
>>>     def bang(message: Any) = {
>>>       self ! message
>>>     }
>>> }
>>> I get the following compiler error:
>>> error: value ! is not a member of Bar2
>
> Yes, it's intentional. I am trying to make a trait that works for any
> class that has a ! method.

But Bar2 doesn't list any requirement that its selftype requires def !...

Why can't you just say:

scala> trait Bar2 {
     | def !(m: Any): Unit;
     | def bang(m: Any) = { this ! m }
     | }
defined trait Bar2

scala> class Foo { def !(m: Any) {} }
defined class Foo

scala> new Foo with Bar2;
res3: Foo with Bar2 = $anon$1@23f39712

or, more ridiculously:

scala> type BangHaver = { def !(m: Any): Unit }
defined type alias BangHaver

scala> trait Bar2 { self: BangHaver => def bang(m: Any) = { self ! m } }
defined trait Bar2

scala> class Foo { def !(m: Any) {} }
defined class Foo

scala> new Foo with Bar2;
res0: Foo with Bar2 = $anon$1@44b1d2a0

-- David

>
> Regards,
>
> Albert
>

Re: Problem with traits

by Albert Strasheim :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello all

On Tue, Nov 3, 2009 at 8:37 AM, David Hall <dlwh@...> wrote:
> But Bar2 doesn't list any requirement that its selftype requires def !...

Thanks, I've figured that part out now.

On to the more complex problem I am actually trying to solve:

import scala.actors.Actor._

case class Ping(other: GenericPinger)

object Actors {
  def main(args : Array[String]) {
    val p1 = new AkkaPinger()
    p1.start
    val p2 = new ScalaPinger()
    p2.start
    p1 ! Ping(p2)
  }
}

trait GenericPinger {
  // XXX would like to get rid of this method in the trait
  def bang(message: AnyRef): Unit

  def reallyReceive: PartialFunction[Any, Unit] = {
    case Ping(other) => {
      println(this + " Ping!")
      other.bang(Ping(this)) // XXX would like to write this as: other
! Ping(this)
    }
  }
}

class AkkaPinger extends se.scalablesolutions.akka.actor.Actor with
GenericPinger {
  def receive: PartialFunction[Any, Unit] = reallyReceive
  // XXX would like to get rid of this extra method
  def bang(message: AnyRef): Unit = {this.!(message)}
}

class ScalaPinger extends scala.actors.Actor with GenericPinger {
  def act() = {
    loop {
      react(reallyReceive)
    }
  }
  // XXX would like to get rid of this extra method
  def bang(message: AnyRef): Unit = {this.!(message)}
}

As far as I understand, the problem I'm having now is that the
signatures for the Scala Actors ! method and the Akka Actors ! method
look slightly different, and I have no idea how to craft a self-type
declaration to make the trait see the respective ! methods.

The Scala Actors ! definition lives here (more or less...):

https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/actors/scala/actors/AbstractReactor.scala

And the Akka Actors one live here:

http://akka.scalablesolutions.se/scaladoc/akka-actors/se/scalablesolutions/akka/actor/Actor.html

Thanks for any thoughts.

Regards,

Albert

P.S. We'll probably settle on using Akka Actors for our library in the
end, but right now I'm trying to code up a little benchmark suite
comparing the two actor libraries, because we are having some
performance issues. So my goal is to minimize the amount of duplicated
code between my actor implementations.

Re: Problem with traits

by David Hall-17 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Nov 3, 2009 at 12:32 AM, Albert Strasheim <fullung@...> wrote:

> Hello all
>
> On Tue, Nov 3, 2009 at 8:37 AM, David Hall <dlwh@...> wrote:
>> But Bar2 doesn't list any requirement that its selftype requires def !...
>
> Thanks, I've figured that part out now.
>
> On to the more complex problem I am actually trying to solve:
>
> import scala.actors.Actor._
>
> case class Ping(other: GenericPinger)
>
> object Actors {
>  def main(args : Array[String]) {
>    val p1 = new AkkaPinger()
>    p1.start
>    val p2 = new ScalaPinger()
>    p2.start
>    p1 ! Ping(p2)

>  }
> }
>
> trait GenericPinger {
>  // XXX would like to get rid of this method in the trait
>  def bang(message: AnyRef): Unit
>
>  def reallyReceive: PartialFunction[Any, Unit] = {
>    case Ping(other) => {
>      println(this + " Ping!")
>      other.bang(Ping(this)) // XXX would like to write this as: other
> ! Ping(this)
>    }
>  }
> }

maybe something like:

trait GenericParser[-Msg] {
  def !(message: Msg):Unit;
   // ...
}

and then

 class AkkaPinger extends se.scalablesolutions.akka.actor.Actor with
GenericPinger[Object];
class ScalaPinger extends scala.actors.Actor with GenericPinger[Any];

?
-- David

>
> class AkkaPinger extends se.scalablesolutions.akka.actor.Actor with
> GenericPinger {
>  def receive: PartialFunction[Any, Unit] = reallyReceive
>  // XXX would like to get rid of this extra method
>  def bang(message: AnyRef): Unit = {this.!(message)}
> }
>
> class ScalaPinger extends scala.actors.Actor with GenericPinger {
>  def act() = {
>    loop {
>      react(reallyReceive)
>    }
>  }
>  // XXX would like to get rid of this extra method
>  def bang(message: AnyRef): Unit = {this.!(message)}
> }
>
> As far as I understand, the problem I'm having now is that the
> signatures for the Scala Actors ! method and the Akka Actors ! method
> look slightly different, and I have no idea how to craft a self-type
> declaration to make the trait see the respective ! methods.
>
> The Scala Actors ! definition lives here (more or less...):
>
> https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/actors/scala/actors/AbstractReactor.scala
>
> And the Akka Actors one live here:
>
> http://akka.scalablesolutions.se/scaladoc/akka-actors/se/scalablesolutions/akka/actor/Actor.html
>
> Thanks for any thoughts.
>
> Regards,
>
> Albert
>
> P.S. We'll probably settle on using Akka Actors for our library in the
> end, but right now I'm trying to code up a little benchmark suite
> comparing the two actor libraries, because we are having some
> performance issues. So my goal is to minimize the amount of duplicated
> code between my actor implementations.