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

Trait and use of super

17 replies
Erik Bruchez
Joined: 2010-02-25,
User offline. Last seen 42 years 45 weeks ago.

All,

I am trying the following:

scala> class Foo {
| def doStuff() {}
| }
defined class Foo

scala> trait Bar {
| this: Foo =>
|
| override def doStuff() {
| super.doStuff()
| }
| }
:10: error: value doStuff is not a member of java.lang.Object
with ScalaObject
super.doStuff()
^

Since my trait Bar is guaranteed to augment a Foo which defines
doStuff(), I thought I would be able to access super.doStuff().

Is this by design? Any simple workaround except having Bar extends
Foo, which I don't want?

-Erik

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Trait and use of super

On Wed, Oct 13, 2010 at 11:06:49AM -0700, Erik Bruchez wrote:
> scala> trait Bar {
> | this: Foo =>
> |
> | override def doStuff() {
> | super.doStuff()
> | }
> | }
> :10: error: value doStuff is not a member of java.lang.Object
> with ScalaObject
> super.doStuff()
> ^
>
> Since my trait Bar is guaranteed to augment a Foo which defines
> doStuff(), I thought I would be able to access super.doStuff().

It's a recent change that you can override methods in the self type at
all. (And I'm not at all sure it was a good change, for reasons brought
up by ingo a couple months ago.) You shouldn't expect self types to act
like a substitute for inheritance - since they won't.

> Is this by design? Any simple workaround except having Bar extends
> Foo, which I don't want?

Why not? Maybe you have a good reason, but there are more fallacious
reasons to avoid that than good ones.

Aaron Novstrup
Joined: 2010-08-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Trait and use of super

trait DoStuff { def doStuff(): Unit }

class Foo {
def doStuff() = { println("foo") }
}

trait Bar extends DoStuff {
this: Foo =>

abstract override def doStuff() = {
super.doStuff()
println("bar")
}
}

scala> (new Foo with Bar).doStuff
foo
bar

scala> (new Foo).doStuff
foo

On 10/13/2010 11:06 AM, Erik Bruchez wrote:
> All,
>
> I am trying the following:
>
> scala> class Foo {
> | def doStuff() {}
> | }
> defined class Foo
>
> scala> trait Bar {
> | this: Foo =>
> |
> | override def doStuff() {
> | super.doStuff()
> | }
> | }
> :10: error: value doStuff is not a member of java.lang.Object
> with ScalaObject
> super.doStuff()
> ^
>
> Since my trait Bar is guaranteed to augment a Foo which defines
> doStuff(), I thought I would be able to access super.doStuff().
>
> Is this by design? Any simple workaround except having Bar extends
> Foo, which I don't want?
>
> -Erik
>
> .
>

Erik Bruchez
Joined: 2010-02-25,
User offline. Last seen 42 years 45 weeks ago.
Re: Trait and use of super

On Wed, Oct 13, 2010 at 12:00 PM, Paul Phillips wrote:
> On Wed, Oct 13, 2010 at 11:06:49AM -0700, Erik Bruchez wrote:
>> scala> trait Bar {
>>      |     this: Foo =>
>>      |
>>      |     override def doStuff() {
>>      |         super.doStuff()
>>      |     }
>>      | }
>> :10: error: value doStuff is not a member of java.lang.Object
>> with ScalaObject
>>                super.doStuff()
>>                      ^
>>
>> Since my trait Bar is guaranteed to augment a Foo which defines
>> doStuff(), I thought I would be able to access super.doStuff().
>
> It's a recent change that you can override methods in the self type at
> all.  (And I'm not at all sure it was a good change, for reasons brought
> up by ingo a couple months ago.) You shouldn't expect self types to act
> like a substitute for inheritance - since they won't.

Thanks. I need to get my head around that a bit more.

>> Is this by design? Any simple workaround except having Bar extends
>> Foo, which I don't want?
>
> Why not? Maybe you have a good reason, but there are more fallacious
> reasons to avoid that than good ones.

Here Foo contains a lot of stuff. Now if I inherit from Foo, my Bar
trait will inherit all of that. Hence my "I don't want".

But with another trait as suggested by Aaron I should be able to get somewhere.

-Erik

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Trait and use of super

On Wed, Oct 13, 2010 at 06:46:52PM -0700, Erik Bruchez wrote:
> >> Is this by design? Any simple workaround except having Bar extends
> >> Foo, which I don't want?
> >
> > Why not? Maybe you have a good reason, but there are more fallacious
> > reasons to avoid that than good ones.
>
> Here Foo contains a lot of stuff. Now if I inherit from Foo, my Bar
> trait will inherit all of that. Hence my "I don't want".

This is in the fallacious category to which I referred. Paraphrasing
your email, you wanted trait T2 below as an alternative to T1 because
you don't want to "inherit all of that", is that right?

class A {
def stuff = 5
def moreStuff = 10
def helloStuff = 15
}

trait T1 extends A {
def f = 5
override def helloStuff = 30
}
trait T2 {
self: A =>

def f = 5
override def helloStuff = 30
}

Let's take a look at what comes out the other end:

% javap T1\$class
Compiled from "A.scala"
public abstract class T1$class extends java.lang.Object{
public static int f(T1);
public static int helloStuff(T1);
public static void $init$(T1);
}

% javap T2\$class
Compiled from "A.scala"
public abstract class T2$class extends java.lang.Object{
public static int f(A);
public static int helloStuff(A);
public static void $init$(A);
}

% javap T1
Compiled from "A.scala"
public interface T1 extends scala.ScalaObject{
public abstract int f();
public abstract int helloStuff();
}

% javap T2
Compiled from "A.scala"
public interface T2 extends scala.ScalaObject{
public abstract int f();
public abstract int helloStuff();
}

Do you have some observable distinction in mind when you speak of this
unwanted inheritance?

barden
Joined: 2010-03-30,
User offline. Last seen 33 weeks 5 days ago.
Lazy val and implicit

Hi all,

I would like to define a lazy val

lazy val a = ...XXX: time consuming...

but XXX needs that some type X is ordered, so it seems that is should be

def a(implicit o: Ordering[X]) = ...XXX...

But now it will consume time everytime I'm asking for 'a'.

Is there a construct to have it equivalent to

lazy val a(implicit o: Ordering[X]) = ...XXX...

?

Thanks in advance,
Volker.

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Lazy val and implicit

lazy val a = {
val o = Ordering[X]; // or = implicitly[Ordering[X]]
...
}

On Thu, Oct 14, 2010 at 2:53 PM, Bardenhorst, Volker Dr.
wrote:
> Hi all,
>
> I would like to define a lazy val
>
>        lazy val a = ...XXX: time consuming...
>
> but XXX needs that some type X is ordered, so it seems that is should be
>
>        def a(implicit o: Ordering[X]) = ...XXX...
>
> But now it will consume time everytime I'm asking for 'a'.
>
> Is there a construct to have it equivalent to
>
>        lazy val a(implicit o: Ordering[X]) = ...XXX...
>
> ?
>
> Thanks in advance,
> Volker.

barden
Joined: 2010-03-30,
User offline. Last seen 33 weeks 5 days ago.
RE: Lazy val and implicit

Hm,

I tried and got

scala> class A[X](x: X, y: X) {
| lazy val a = {
| val o = implicitly[Ordering[X]]
| o.max(x, y)
| }
| }
:7: error: could not find implicit value for parameter e: Ordering[X]
val o = implicitly[Ordering[X]]

Did I miss something?

Cheers,
Volker.

-----Original Message-----
From: Jason Zaugg [mailto:jzaugg [at] gmail [dot] com]
Sent: 14 October 2010 14:56
To: Bardenhorst, Volker Dr.
Cc: scala-user [at] listes [dot] epfl [dot] ch
Subject: Re: [scala-user] Lazy val and implicit

lazy val a = {
val o = Ordering[X]; // or = implicitly[Ordering[X]]
...
}

On Thu, Oct 14, 2010 at 2:53 PM, Bardenhorst, Volker Dr.
wrote:
> Hi all,
>
> I would like to define a lazy val
>
>        lazy val a = ...XXX: time consuming...
>
> but XXX needs that some type X is ordered, so it seems that is should
> be
>
>        def a(implicit o: Ordering[X]) = ...XXX...
>
> But now it will consume time everytime I'm asking for 'a'.
>
> Is there a construct to have it equivalent to
>
>        lazy val a(implicit o: Ordering[X]) = ...XXX...
>
> ?
>
> Thanks in advance,
> Volker.

Moritz Uhlig
Joined: 2010-01-08,
User offline. Last seen 42 years 45 weeks ago.
Re: Lazy val and implicit

Am 14.10.2010 um 15:20 schrieb Bardenhorst, Volker Dr.:

> Hm,
>
> I tried and got
>
> scala> class A[X](x: X, y: X) {
> | lazy val a = {
> | val o = implicitly[Ordering[X]]
> | o.max(x, y)
> | }
> | }
> :7: error: could not find implicit value for parameter e: Ordering[X]
> val o = implicitly[Ordering[X]]
>
> Did I miss something?

Your class definition would have to look like

class A[X : Ordering](x: X, y: X) {...}

as otherwise you cannot make sure that such an implicit value exists.
You already need that parameter at instance construction time.

You can of course also write it like this:

class A[X](x: X, y: X)(implicit o: Ordering[X]) {
lazy val a = o.max(x, y)
}

as you always need the Ordering[X] parameter.

Regards,

Moritz

barden
Joined: 2010-03-30,
User offline. Last seen 33 weeks 5 days ago.
RE: Lazy val and implicit

I would like to attach this to the method and val and for the former one I did like this

class A[X](val x: X, val y: X) {
...
bunch of other methods not relying on Ordering[X]
...
def f(that: A[X])(implicit o: Ordering[X]) = o.max(this.x, that.x)
}

And now wonder whether I could have

class A[X](val x: X, val y: X) {
...
bunch of other methods not relying on Ordering[X]
...
def f(that: A[X])(implicit o: Ordering[X]) = o.max(this.x, that.x)

"lazy val a(implicit o: Ordering[X]) = ..."
}

But maybe I'm expecting to much and I just have to use def instead of lazy val

-----Original Message-----
From: Moritz Uhlig [mailto:moritz [dot] uhlig [at] jsolution [dot] de]
Sent: 14 October 2010 15:27
To: Bardenhorst, Volker Dr.
Cc: Jason Zaugg; scala-user [at] listes [dot] epfl [dot] ch
Subject: Re: [scala-user] Lazy val and implicit

Am 14.10.2010 um 15:20 schrieb Bardenhorst, Volker Dr.:

> Hm,
>
> I tried and got
>
> scala> class A[X](x: X, y: X) {
> | lazy val a = {
> | val o = implicitly[Ordering[X]]
> | o.max(x, y)
> | }
> | }
> :7: error: could not find implicit value for parameter e: Ordering[X]
> val o = implicitly[Ordering[X]]
>
> Did I miss something?

Your class definition would have to look like

class A[X : Ordering](x: X, y: X) {...}

as otherwise you cannot make sure that such an implicit value exists.
You already need that parameter at instance construction time.

You can of course also write it like this:

class A[X](x: X, y: X)(implicit o: Ordering[X]) {
lazy val a = o.max(x, y)
}

as you always need the Ordering[X] parameter.

Regards,

Moritz

Razvan Cojocaru 3
Joined: 2010-07-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Lazy val and implicit

Possibly a little off but for stuff that takes time I think a Future
is better, so
... {
Private[this] Val f = ... // makes a future
Lazy val a = f.get // or whatever gets you the future value...
...
}

That does wonders for responsiveness, eh?

Cheers,
Razie

On 10/14/10, Bardenhorst, Volker Dr. wrote:
> Hi all,
>
> I would like to define a lazy val
>
> lazy val a = ...XXX: time consuming...
>
> but XXX needs that some type X is ordered, so it seems that is should be
>
> def a(implicit o: Ordering[X]) = ...XXX...
>
> But now it will consume time everytime I'm asking for 'a'.
>
> Is there a construct to have it equivalent to
>
> lazy val a(implicit o: Ordering[X]) = ...XXX...
>
> ?
>
> Thanks in advance,
> Volker.

Aydjen
Joined: 2009-08-21,
User offline. Last seen 1 year 28 weeks ago.
RE: Lazy val and implicit

Dr. Volker Bardenhorst wrote:
> But maybe I'm expecting to much and I just have to use def instead of
> lazy val

If you'd use a def, you could still cache the computed value, e.g.:

class A[X](val x: X, val y: X) {
private[this] var fResult: Option[X] = None

def f(that: A[X])(implicit o: Ordering[X]) = synchronized {
fResult getOrElse {
val n = o.max(this.x, that.x)
fResult = Some(n)
n
}
}
}

That's not really pretty though.

-
Andreas

barden
Joined: 2010-03-30,
User offline. Last seen 33 weeks 5 days ago.
RE: Lazy val and implicit

Yes, not really pretty but also not really ugly, thanks a lot

-----Original Message-----
From: Andreas Flierl [mailto:andreas [at] flierl [dot] eu]
Sent: 14 October 2010 16:53
To: Bardenhorst, Volker Dr.
Cc: scala-user [at] listes [dot] epfl [dot] ch
Subject: RE: [scala-user] Lazy val and implicit

Dr. Volker Bardenhorst wrote:
> But maybe I'm expecting to much and I just have to use def instead of
> lazy val

If you'd use a def, you could still cache the computed value, e.g.:

class A[X](val x: X, val y: X) {
private[this] var fResult: Option[X] = None

def f(that: A[X])(implicit o: Ordering[X]) = synchronized {
fResult getOrElse {
val n = o.max(this.x, that.x)
fResult = Some(n)
n
}
}
}

That's not really pretty though.

-
Andreas

nilskp
Joined: 2009-01-30,
User offline. Last seen 1 year 27 weeks ago.
Re: Lazy val and implicit
On Thu, Oct 14, 2010 at 7:53 AM, Bardenhorst, Volker Dr. <Volker [dot] Bardenhorst [at] eon [dot] com> wrote:
Is there a construct to have it equivalent to

       lazy val a(implicit o: Ordering[X]) = ...XXX...

If your value is parameter dependent, it can't be a single value. What if it was called a second time with a different Ordering? This would be idempotent:  def a[X](implicit: o: Ordering[X]) = map.getOrElseUpdate(o, new XXX(o)) // or whatever construction
barden
Joined: 2010-03-30,
User offline. Last seen 33 weeks 5 days ago.
RE: Lazy val and implicit
good point,   does it mean that my class A orginal intendend to be immutabel is broken here to mutable? using Andreas' solution:  

class A[X](val x: X, val y: X) {

    private[this] var fResult: Option[X] = None

    def f(that: A[X])(implicit o: Ordering[X]) = synchronized {

        fResult getOrElse {

            val n = o.max(this.x, that.x)

            fResult = Some(n)

            n

        }

    }

}

seems to imply "first ordering serves first". Is that then slightly immutable? When it is possible to fix the Ordering of some type (what is suitable for my purposes) is it then immutable again?

probably I have to think about my construction

 

cheers


From: Nils Kilden-Pedersen [mailto:nilskp [at] gmail [dot] com]
Sent: 14 October 2010 18:37
To: Bardenhorst, Volker Dr.
Cc: scala-user [at] listes [dot] epfl [dot] ch
Subject: Re: [scala-user] Lazy val and implicit

On Thu, Oct 14, 2010 at 7:53 AM, Bardenhorst, Volker Dr. <Volker [dot] Bardenhorst [at] eon [dot] com> wrote:
Is there a construct to have it equivalent to

       lazy val a(implicit o: Ordering[X]) = ...XXX...

If your value is parameter dependent, it can't be a single value. What if it was called a second time with a different Ordering? This would be idempotent:   def a[X](implicit: o: Ordering[X]) = map.getOrElseUpdate(o, new XXX(o)) // or whatever construction
Erik Bruchez
Joined: 2010-02-25,
User offline. Last seen 42 years 45 weeks ago.
Re: Trait and use of super

> This is in the fallacious category to which I referred.  Paraphrasing
> your email, you wanted trait T2 below as an alternative to T1 because
> you don't want to "inherit all of that", is that right?

[snip]

> Let's take a look at what comes out the other end:

Looks pretty similar! I think my root issue was understanding what it
meant for a trait to "extend" a class. Seems like you covered this
here:

http://www.scala-lang.org/node/3112#comment-11558

So both "extends" and self types set a limitation on where a trait can
be instantiated.

Next step: understanding the difference(s) between the two.

-Erik

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Trait and use of super

On Sun, Oct 17, 2010 at 05:09:08PM -0700, Erik Bruchez wrote:
> So both "extends" and self types set a limitation on where a trait can
> be instantiated.
>
> Next step: understanding the difference(s) between the two.

Some are:

1) Self-types let you form cycles which you can't do via inheritance.

scala> trait T1 { self: T2 => } ; trait T2 { self: T1 => }
defined trait T1
defined trait T2

2) Self-types require all inheriting traits to have a compatible
self-type: traits extending classes impose no similar requirement.

scala> class Q ; trait T1 extends Q ; trait T2 extends T1
defined class Q
defined trait T1
defined trait T2

scala> class Q ; trait T1 { self: Q => } ; trait T2 extends T1
:8: error: illegal inheritance;
self-type T2 does not conform to T1's selftype T1 with Q
class Q ; trait T1 { self: Q => } ; trait T2 extends T1
^

3) Self-types can express constraints which cannot be expressed via
inheritance.

scala> type Bippy = { def bippy(): Int }
defined type alias Bippy

scala> trait T1 { self: Bippy => }
defined trait T1

scala> class A extends T1
:7: error: illegal inheritance;
self-type A does not conform to T1's selftype T1 with Bippy
class A extends T1
^

scala> class A extends T1 { def bippy(): Int = "5" }
:7: error: type mismatch;
found : java.lang.String("5")
required: Int
class A extends T1 { def bippy(): Int = "5" }
^

scala> class A extends T1 { def bippy(): Int = 5 }
defined class A

Erik Bruchez
Joined: 2010-02-25,
User offline. Last seen 42 years 45 weeks ago.
Re: Trait and use of super

>> Next step: understanding the difference(s) between the two.
>
> Some are:
>
> 1) Self-types let you form cycles which you can't do via inheritance.
>
> scala> trait T1 { self: T2 => } ; trait T2 { self: T1 =>  }
> defined trait T1
> defined trait T2
>
> 2) Self-types require all inheriting traits to have a compatible
> self-type: traits extending classes impose no similar requirement.
>
> scala> class Q ; trait T1 extends Q ; trait T2 extends T1
> defined class Q
> defined trait T1
> defined trait T2
>
> scala> class Q ; trait T1 { self: Q => } ; trait T2 extends T1
> :8: error: illegal inheritance;
>  self-type T2 does not conform to T1's selftype T1 with Q
>       class Q ; trait T1 { self: Q => } ; trait T2 extends T1
>                                                            ^
>
> 3) Self-types can express constraints which cannot be expressed via
> inheritance.
>
> scala> type Bippy = { def bippy(): Int }
> defined type alias Bippy
>
> scala> trait T1 { self: Bippy => }
> defined trait T1
>
> scala> class A extends T1
> :7: error: illegal inheritance;
>  self-type A does not conform to T1's selftype T1 with Bippy
>       class A extends T1
>                       ^
>
> scala> class A extends T1 { def bippy(): Int = "5" }
> :7: error: type mismatch;
>  found   : java.lang.String("5")
>  required: Int
>       class A extends T1 { def bippy(): Int = "5" }
>                                               ^
>
> scala> class A extends T1 { def bippy(): Int = 5 }
> defined class A

Thanks, that helps!

-Erik

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