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

Abstract Types: Example from "Scala Experiment" not working

4 replies
Thorsten
Joined: 2011-07-29,
User offline. Last seen 42 years 45 weeks ago.

Hello List,
I tried to experiment with the abstract type example from Odersky
scala_experiment.pdf (on the web). It does compile and run (after
changing the type names first letter to upper-case), but the
result is not what I would expect.
Thanks for any hints
Thorsten

// code
object myClass extends Application {
abstract class AbsCell {
type T;
val init : T;
private var value : T = init;
def get : T = value;
def set(x : T): Unit = { value = x }
}

val cell = new AbsCell { type T = Int; val init = 1 }
cell.set(cell.get * 2)
println(cell.get) // added by me
}

// result
$ scalac myClassFilename.scala
$ scala myClass
0 // should't this be (1 * 2), it seems like init is never assigned

Alex Repain
Joined: 2010-07-27,
User offline. Last seen 1 year 31 weeks ago.
Re: Abstract Types: Example from "Scala Experiment" not working
This problem seems to be due to constructor linearization. When assigning

val cell = new AbsCell { type T = Int; val init = 1 }

AbsCell is fully initialized and THEN T and init are given values. Since every abstract field is then defined, this compiles, but value has been given a default value 0 (java interop ?). init has been changed, but this doesn't affect value because the initialization order. You can get to your expected result by turning AbsCell to a trait and changing the construction order :

val cell = new{ type T = Int; val init = 1 } with AbsCell
I knew that this behavior existed for traits, but this is pretty unintuitive, to see automatic initialization of abstract values even in abstract classes...

2011/8/13 Thorsten <quintfall [at] googlemail [dot] com>
Hello List,
I tried to experiment with the abstract type example from Odersky
scala_experiment.pdf (on the web). It does compile and run (after
changing the type names first letter to upper-case), but the
result is not what I would expect.
Thanks for any hints
Thorsten

// code
object myClass extends Application {
abstract class AbsCell {
 type T;
 val init : T;
 private var value : T = init;
 def get : T = value;
 def set(x : T): Unit = { value = x }
}


val cell = new AbsCell { type T = Int; val init = 1 }
cell.set(cell.get * 2)
println(cell.get)  // added by me
}

// result
$ scalac myClassFilename.scala
$ scala myClass
0  // should't this be (1 * 2), it seems like init is never assigned




--
Alex REPAIN
ENSEIRB-MATMECA - student
TECHNICOLOR R&D - intern
BORDEAUX I      - master's student
SCALA           - enthusiast


Thorsten
Joined: 2011-07-29,
User offline. Last seen 42 years 45 weeks ago.
Re: Abstract Types: Example from "Scala Experiment" not working

Alex Repain
writes:

> This problem seems to be due to constructor linearization. When assigning
>
> val cell = new AbsCell { type T = Int; val init = 1 }
>
> AbsCell is fully initialized and THEN T and init are given
> values. Since every abstract field is then defined, this compiles, but
> value has been given a default value 0 (java interop ?). init has been
> changed, but this doesn't affect value because the initialization
> order. You can get to your expected result by turning AbsCell to a
> trait and changing the construction order :
>
> val cell = new{ type T = Int; val init = 1 } with AbsCell
>
> I knew that this behavior existed for traits, but this is pretty
> unintuitive, to see automatic initialization of abstract values even
> in abstract classes...
>
> 2011/8/13 Thorsten
>
> Hello List,
> I tried to experiment with the abstract type example from Odersky
> scala_experiment.pdf (on the web). It does compile and run (after
> changing the type names first letter to upper-case), but the
> result is not what I would expect.
> Thanks for any hints
> Thorsten
>
> // code
> object myClass extends Application {
> abstract class AbsCell {
>  type T;
>  val init : T;
>  private var value : T = init;
>  def get : T = value;
>  def set(x : T): Unit = { value = x }
> }
>
> val cell = new AbsCell { type T = Int; val init = 1 }
> cell.set(cell.get * 2)
> println(cell.get)  // added by me
> }
>
> // result
> $ scalac myClassFilename.scala
> $ scala myClass
> 0  // should't this be (1 * 2), it seems like init is never assigned

Thats really surprising to me - did the language change that much since
"Scalable Component Abstractions" by Odersky/Zenger was published in 2005
(because thats where this example was originally published, I guess)? That
seemed to be such a basic example to me, and I thought it was a for the
use of abstract type members.

I must admit I find your version less intuitive - is that the official
way to use abstract type members now? I find that kind of hard to
believe.

Thanks for your help.
Cheers
Thorsten

y
Joined: 2011-07-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Abstract Types: Example from "Scala Experiment" not working

Yes, things change. I've seen examples from later papers (by Oliveira
if memory serves) that don't compile anymore.

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: Abstract Types: Example from "Scala Experiment" not wor

On Sat, Aug 13, 2011 at 18:06, Thorsten wrote:
> Alex Repain
> writes:
>
>> This problem seems to be due to constructor linearization. When assigning
>>
>> val cell = new AbsCell { type T = Int; val init = 1 }
>>
>> AbsCell is fully initialized and THEN T and init are given
>> values. Since every abstract field is then defined, this compiles, but
>> value has been given a default value 0 (java interop ?). init has been
>> changed, but this doesn't affect value because the initialization
>> order. You can get to your expected result by turning AbsCell to a
>> trait and changing the construction order :
>>
>> val cell = new{ type T = Int; val init = 1 } with AbsCell
>>
>> I knew that this behavior existed for traits, but this is pretty
>> unintuitive, to see automatic initialization of abstract values even
>> in abstract classes...

The language did change much, but not very much where this is concerned.

All that happened was the introduction of better initialization rules.
At the place where { // code } appears, it can depend on everything
before it having been initialized. Consider this:

val cell = newAbsCell { type T = Int; val x = get; val init = 1 }
val x = cell.x

What is the value of "x"? Should it execute "val init = 1" before "val
x = get"? And is "val x = get" supposed to be executed before or after
"private var value : T = init"? How can you tell which comes first?
Should Scala try to graph all possible initialization paths and figure
out a dependency tree to get things working? Mind you, newAbsCell
might well be in a JAR file, in a library. How could Scala split its
constructor so that its execution be staged in parts, with unknown
code being executed in between them? And how would that be ever be
compatible with Java and the JVM?

So things are simple: place the initialization where (when) you want
it to happen. After "newAbsCell", then it runs after that. Before it,
and it will run before.

It doesn't help much people who write convoluted code with abstract
member initialization and non-abstract member initialization depending
on abstract members, but it has the big merit of being simple, easy to
understand, and predictable.

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