self reference value

139 views
Skip to first unread message

Chin-Lung Chang

unread,
Jun 29, 2012, 11:53:33 PM6/29/12
to scala...@googlegroups.com
Hi everybody, 

I encountered a value initialization problem: 

class Top 

class X(val v : Top) extends Top 
class Y extends Top 

X is a class constructed using other Top typed object, such as X or Y. Which means it may be constructed using itself. For example, 

val x = new X(x) 

The compiler will work, but when I access the v field, I got null returned. 

scala> x.v 
res9: Top = null 

I tried lazy initialization and by-name parameter, getting the same result. My Scala version is 2.9.1. Anyone can help me ??? 

Regards, 
Chin-Lung Chang

Raymond Tay

unread,
Jun 30, 2012, 12:23:11 AM6/30/12
to scala-user
Re-sending ....

---------- Forwarded message ----------
From: Raymond Tay <raymond...@gmail.com>
Date: Sat, Jun 30, 2012 at 12:19 PM
Subject: Re: [scala-user] self reference value
To: Chin-Lung Chang <chin...@gmail.com>


I'm not too certain about the intricacies w.r.t recursive types in Scala but does this work for you?

scala> val x = new { override val v = new X(new Top) } with X(v)
x: X{val v: X} = $anon$1@1be72d8

scala> x.v
res3: X = X@876c964



--
http://about.me/rayt

Dave

unread,
Jun 30, 2012, 11:19:41 AM6/30/12
to scala-user
Maybe this?

forwardreference.scala
======================
class Top
class X(v : => Top) extends Top {
lazy val _v = v
def v() : Top = _v
}
class Y extends Top

object Main extends App {

val x: X = new X(x)

println(x.v)
println(x.v.getClass.getName)
}

Output:
=======
C:\scala-2.10.0-M4\myexamples>scala Main
X@13adc56
X

Dave

unread,
Jun 30, 2012, 11:30:54 AM6/30/12
to scala-user
This works too. Leave the lazy val field away.

class Top
class X(v : => Top) extends Top {
def v() : Top = v
> > Chin-Lung Chang- Tekst uit oorspronkelijk bericht niet weergeven -
>
> - Tekst uit oorspronkelijk bericht weergeven -

Josh Suereth

unread,
Jun 30, 2012, 11:46:40 AM6/30/12
to Dave, scala-user

That's not a good idea in general, but works for self referential v.

You want the lazy val to avoid recomputing v...

Chin-Lung Chang

unread,
Jun 30, 2012, 12:10:32 PM6/30/12
to scala...@googlegroups.com
Thanks Dave,

Excellent solution by combining the by-name parameter and lazy field.

May I know if it is possible to use by-name parameter for repeated parameter ?

for example, I may want to pass in the constructor a lot of Top objects.

class X (v: => Top*)  // compile error

Thanks a lot again

Regards,
Chin-Lung Chang

Sonnenschein

unread,
Jun 30, 2012, 1:07:41 PM6/30/12
to scala-user
> class X (v: => Top*)  // compile error

you may use the following workaround:

final class ByName[A](block: => A) {
def apply(): A = block
}
implicit def toHolder[A](block: => A) =
new ByName(block)
class X (v: => ByName[Top]*)

Peter

Dave

unread,
Jun 30, 2012, 1:13:47 PM6/30/12
to scala-user
No

https://issues.scala-lang.org/browse/SI-237

http://www.scala-lang.org/node/4272 (quote Tue, 2009-11-24, 16:27
"(Opened 2 years ago, so don't hold your breath)")


Probably you want something like this:

class Top
class X(v : (=> Top)*) extends Top {
lazy val _v = v
def v() : Seq[Top] = _v
}
class Y extends Top

object Main extends App {

val x: X = new X(new X(x),new X(x))

}

C:\scala-2.10.0-M4\myexamples>scalac forwardreference.scala
forwardreference.scala:30: error: no by-name parameter type allowed
here
class X(v : (=> Top)*) extends Top {
^
one error found

Raymond Tay

unread,
Jun 30, 2012, 3:06:26 PM6/30/12
to scala...@googlegroups.com
Didn't know one could do that. Thanks for showing how. I've a question: why would I need to do something like that?

Dave

unread,
Jun 30, 2012, 5:38:24 PM6/30/12
to scala-user
Btw:
this is the issue for adding lazy parameters in method and
constructor

https://issues.scala-lang.org/browse/SI-240 (for upvoting and
following)

Then you can simply write
class X(lazy val v : Top) extends Top

with more efficient underlying code than the workaround

Reply all
Reply to author
Forward
0 new messages