Two questions on Unique References

22 views
Skip to first unread message

Dmitry Grigoriev

unread,
Apr 13, 2011, 3:28:18 PM4/13/11
to scala-language
Hello all!

Here I found that unique types plugin are to be included into 2.9
"official" part of the language:
http://stackoverflow.com/questions/5065861/programming-languages-based-on-linear-types

Q1: is that true?

Considering example in the section 1.3 here: http://lamp.epfl.ch/~phaller/readme_uniqueness.html

Q2: what must I do if I want not "same method with same arg (BTW, on
same instance?) can be called only once", but "any method on same
instance can be called only once"? That is, I want to encode state
machine into type system. For example, after I call "val file2 =
file1.open(...)", I cannot call any other method on the same file1,
but I continue to work on file2. After I call "fileN.close()" which
returns Unit, I cannot call anything else neither on fileN nor on any
previous file instance.

I can only imagine some singleton backend like this:

class FileImpl {
def open(...): FileImpl
def close(): Unit
}
object FileImpl {
// Every call to any File method passes through here,
// so any File instance can receive method call only once.
def get(f: File @Unique): FileImpl
}
class File {
def open(...) = FileImpl.get(f).open(...)
def close() = FileImpl.get(f).close()
}

Thanks.

coach3pete

unread,
Apr 13, 2011, 6:59:11 PM4/13/11
to scala-l...@googlegroups.com
I have several traits that can be stacked in any order. When I call toString on an object with several traits mixed in, I'd like toString executed for each trait that extends a marker trait.

1) How could the following be designed so that toString is called for the traits mixed in? Tried to have each trait's toString prepend a call its parent trait toString, but that failed.

scala> trait A {
| val a: String
| override def toString = a
| }
defined trait A

scala> trait B {
| val b: String
| override def toString = b
| }
defined trait B

scala> val a = new A {val a="A"}
a: java.lang.Object with A = A

scala> println(a)
A

scala> val b = new B {val b="B"}
b: java.lang.Object with B = B

scala> println(b)
B

scala> val ab = new A with B {val a="A"; val b="B"}
ab: java.lang.Object with A with B = B

scala> println(ab)
B

scala> val ba = new B with A {val a="A"; val b="B"}
ba: java.lang.Object with B with A = A

scala> println(ba)
A

2) Why do I not get the same output from these two statements then both ab and ba have A mixed in?

scala> println(if(ab.isInstanceOf[A]) ab.asInstanceOf[A])
B

scala> println(if(ba.isInstanceOf[A]) ba.asInstanceOf[A])
A

Daniel Sobral

unread,
Apr 13, 2011, 8:52:01 PM4/13/11
to scala-l...@googlegroups.com, coach3pete
1)

scala> trait A {
| val a: String

| abstract override def toString = a + super.toString
| }
defined trait A

scala> trait B {
| val b: String

| abstract override def toString = b + super.toString
| }
defined trait B

scala> val ab = new A with B { val a = "A"; val b = "B" }
ab: java.lang.Object with A with B = BA$anon$1@384e9bea

scala> println(ab)
BA$line3.$read$$iw$$iw$$anon$1@384e9bea

scala> val ba = new B with A { val a = "A"; val b = "B" }
ba: java.lang.Object with B with A = AB$anon$1@24748417

scala> println(ba)
AB$line5.$read$$iw$$iw$$anon$1@24748417

The $line...etc is from the default toString.

2) Because what the compiler thinks a type is have no relevance to
method overrides. If it did, then inheritance would be pretty silly.
Any place where you had def f(x: A), it wouldn't matter what class you
actually passed to f, x would always act like an A.

--
Daniel C. Sobral

I travel to the future all the time.

coach3pete

unread,
Apr 13, 2011, 10:47:13 PM4/13/11
to scala-l...@googlegroups.com, Daniel Sobral
Thanks Daniel. Adding a Base trait and a little more work to get desired behavior. Perhaps there is a better way?

trait Base {
override def toString = ""
}
trait A extends Base {
val a: String
abstract override def toString = (if(super.toString.size > 0) (super.toString+ "\n\t") else "") + a
}
trait B extends Base {
val b: String
abstract override def toString = (if(super.toString.size > 0) (super.toString + "\n\t") else "") + b


}
val a = new A {val a="A"}

println(a)


val b = new B {val b="B"}

println(b)
val ab = new Base with A with B {val a="A"; val b="B"}
println(ab)
val ba = new Base with B with A {val a="A"; val b="B"}
println(ba)

Erik Peterson
m: (281) 804-9023
e...@ardec.com

Daniel Sobral

unread,
Apr 14, 2011, 10:25:09 AM4/14/11
to coach3pete, scala-l...@googlegroups.com
If there's a better way depends on what you actually want.

coach3pete

unread,
Apr 14, 2011, 5:33:57 PM4/14/11
to scala-l...@googlegroups.com, Daniel Sobral
Well, I'm trying to aggregate function output (toString in this case) of stacked traits and my solution, though workable, smells by testing for an empty string "" in the Base marker trait. I thought using a marker trait like this might work:

scala> trait Base
defined trait Base

scala> trait A extends Base {
     | val a: String
     | abstract override def toString = (if(super.isInstanceOf[Base]) "" else (super.toString+ "\n\t") ) + a
     | }
<console>:39: error: super not allowed here: use this.isInstanceOf instead
       abstract override def toString = (if(super.isInstanceOf[Base]) "" else (super.toString+ "\n\t") ) + a
                                                  ^
...but why is super not allowed here?





trait Base
trait A extends Base {
val a: String
abstract override def toString = (if(super.isInstanceOf[Base]) "" else (super.toString+ "\n\t") ) + a
}





scala> trait Base {
     | override def toString = ""
     | }
defined trait Base

scala> trait A extends Base {
     | val a: String
     | abstract override def toString = (if(!super.isInstanceOf[Base]) (super.toString+ "\n\t")  else "") + a
     | }
<console>:19: error: super not allowed here: use this.isInstanceOf instead
       abstract override def toString = (if(!super.isInstanceOf[Base]) (super.toString+ "\n\t")  else "") + a

Paul Phillips

unread,
Apr 14, 2011, 6:21:29 PM4/14/11
to scala-l...@googlegroups.com, coach3pete, Daniel Sobral
On 4/14/11 2:33 PM, coach3pete wrote:
> <console>:39: error: super not allowed here: use this.isInstanceOf instead
> abstract override def toString = (if(super.isInstanceOf[Base]) "" else
> (super.toString+ "\n\t") ) + a
> ^
> ...but why is super not allowed here?

The reason there's a message is that it had a habit of crashing the
compiler, because super needs a lot of special handling and there are
some places more likely to take programmers by surprise than other
places. But what is the situation where you think you'd get an an
answer from super.isInstanceOf[Foo] than you wouldn't get from
this.isInstanceOf[Foo] ? There's a pretty tiny zone of potential
difference there, and if I grant for the sake of argument a legitimate
need to see into that zone, it won't work right anyway.

Reply all
Reply to author
Forward
0 new messages