This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Generics and bounds

6 replies
edmondo1984
Joined: 2011-09-14,
User offline. Last seen 28 weeks 4 days ago.
Dear All,I would need to implement inside a scala object two apply functions, receiving as  parameter f :()=> T.
The first one should be called when T is Unit, the other when T is not Unit.

How can I obtain this by using generics and bounds?
Thank you very muchEdmondo 
milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
Re: Generics and bounds

On Sun, Dec 11, 2011 at 1:33 PM, Edmondo Porcu wrote:
> Dear All,
> I would need to implement inside a scala object two apply functions,
> receiving as  parameter f :()=> T.
>
> The first one should be called when T is Unit, the other when T is not Unit.
>
> How can I obtain this by using generics and bounds?

You can't with just generics and bounds, because the post-erasure
signatures of both methods will be the same. If you really have to
overload in this way (and I'd recommend that you try and avoid it if
possible) you best bet it to use a disambiguating DummyImplicit
(defined in Predef),

trait Overloaded {
def apply[T](f : () => T) = "one"
def apply(f : () => Unit)(implicit dummy : DummyImplicit) = "two"
}

val o = new Overloaded {}

val f1 = () => 23
val f2 = () => ()

assert(o(f1) == "one")
assert(o(f2) == "two")

Cheers,

Miles

edmondo1984
Joined: 2011-09-14,
User offline. Last seen 28 weeks 4 days ago.
Re: Generics and bounds
Ok, let's try to tell you what I am trying to do and maybe there is a better solution. Anyways DummyImplcit is now deprecated, and the doc says : Use From => To
I am creating a library for periodic events which will occurr according to a given time distribution. The problem is that some events would bear a result (f : () => T where T!=Unit, and other would not. 
abstract class RandomDistributedEvent[T] {
  def millisToNextEvent: Int;  protected var active = true;  var threadName="RandomDistributedEvent"   def run = {    val thread = new Thread(threadName) {      override def run() {        while (active) {          Thread.sleep(millisToNextEvent);          action;        }      }    }    thread.start();  }
  def action:T;  def stop = {    active=false
  }; }
abstract class RandomDistributedEventWithResult[T] extends RandomDistributedEvent[T] {  private val resultQueue = new LinkedBlockingQueue[T]();
  override def run = {     val thread = new Thread(threadName) {      override def run() {        while (active) {          Thread.sleep(millisToNextEvent)          resultQueue.put(action);         }      }    }
    thread.start();  }
  def result:T = resultQueue.poll();}
These are the two classes for the events, but you understand that to instanciate them I run into the problem we were just discussing.
How can this be developed more effectively?
Best Regards


2011/12/11 Miles Sabin <miles@milessabin.com>
On Sun, Dec 11, 2011 at 1:33 PM, Edmondo Porcu <edmondo.porcu@gmail.com> wrote:
> Dear All,
> I would need to implement inside a scala object two apply functions,
> receiving as  parameter f :()=> T.
>
> The first one should be called when T is Unit, the other when T is not Unit.
>
> How can I obtain this by using generics and bounds?

You can't with just generics and bounds, because the post-erasure
signatures of both methods will be the same. If you really have to
overload in this way (and I'd recommend that you try and avoid it if
possible) you best bet it to use a disambiguating DummyImplicit
(defined in Predef),

 trait Overloaded {
   def apply[T](f : () => T) = "one"
   def apply(f : () => Unit)(implicit dummy : DummyImplicit) = "two"
 }

 val o = new Overloaded {}

 val f1 = () => 23
 val f2 = () => ()

 assert(o(f1) == "one")
 assert(o(f2) == "two")

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
gtalk: miles@milessabin.com
skype: milessabin
g+: http://www.milessabin.com
http://twitter.com/milessabin
http://www.chuusai.com/

milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
Re: Generics and bounds

On Sun, Dec 11, 2011 at 1:52 PM, Edmondo Porcu wrote:
> Ok, let's try to tell you what I am trying to do and maybe there is a better
> solution. Anyways DummyImplcit is now deprecated, and the doc says : Use
> From => To

No it's not. You've misread the source. The deprecation you're seeing is of <%<.

> These are the two classes for the events, but you understand that to
> instanciate them I run into the problem we were just discussing.

Sure ...

Cheers,

Miles

Lars Hupel
Joined: 2010-06-23,
User offline. Last seen 44 weeks 3 days ago.
Re: Generics and bounds

> If you really have to overload in this way (and I'd recommend that
> you try and avoid it if possible) […]

One way to avoid that is to use a type class priority hierarchy:

case class ToT[T](f: (() => T) => String)

trait LowPriorityT {
implicit def genericToT[T] = ToT[T](func => "one")
}

object ToT extends LowPriorityT {
implicit def toUnit = ToT[Unit](func => "two")
}

class Overloaded {
def apply[T : ToT](func: () => T) = implicitly[ToT[T]].f(func)
}

// now the rest is basically the same…

val o = new Overloaded

val f1 = () => 23
val f2 = () => ()

assert(o(f1) == "one")
assert(o(f2) == "two")

Michael Schmitz
Joined: 2011-11-01,
User offline. Last seen 42 years 45 weeks ago.
Re: Generics and bounds

I've seen this solution a couple of times on the list now. How does
it work? Scala disambiguates with the runtime type in this case?
When does Scala choose a method based on the runtime type?

Peace. Michael

On Sun, Dec 11, 2011 at 5:44 AM, Miles Sabin wrote:
> On Sun, Dec 11, 2011 at 1:33 PM, Edmondo Porcu wrote:
>> Dear All,
>> I would need to implement inside a scala object two apply functions,
>> receiving as  parameter f :()=> T.
>>
>> The first one should be called when T is Unit, the other when T is not Unit.
>>
>> How can I obtain this by using generics and bounds?
>
> You can't with just generics and bounds, because the post-erasure
> signatures of both methods will be the same. If you really have to
> overload in this way (and I'd recommend that you try and avoid it if
> possible) you best bet it to use a disambiguating DummyImplicit
> (defined in Predef),
>
>  trait Overloaded {
>    def apply[T](f : () => T) = "one"
>    def apply(f : () => Unit)(implicit dummy : DummyImplicit) = "two"
>  }
>
>  val o = new Overloaded {}
>
>  val f1 = () => 23
>  val f2 = () => ()
>
>  assert(o(f1) == "one")
>  assert(o(f2) == "two")
>
> Cheers,
>
>
> Miles
>
> --
> Miles Sabin
> tel: +44 7813 944 528
> gtalk: miles@milessabin.com
> skype: milessabin
> g+: http://www.milessabin.com
> http://twitter.com/milessabin
> http://www.chuusai.com/

Lars Hupel
Joined: 2010-06-23,
User offline. Last seen 44 weeks 3 days ago.
Re: Generics and bounds

> I've seen this solution a couple of times on the list now. How does
> it work? Scala disambiguates with the runtime type in this case?
> When does Scala choose a method based on the runtime type?

The Scala compiler translates curried methods definitions to uncurried
methods. The JVM then sees two methods called `apply`, roughly like that:

def apply(f: Function0) = "one"
def apply(f: Function0, dummy: DummyImplicit) = "two"

Now they are really different methods. As the compiler is able to
disambiguate the call statically, it can generate the byte code to
invoke either of these.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland