Only if you have an infinite stack and an awful lot of time ;-)
Alternatively you could try this,
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Root(child0: => Child) {
lazy val child = child0
}
class Child(parent0: => Root) {
lazy val parent = parent0
}
// Exiting paste mode, now interpreting.
defined class Root
defined class Child
scala> val root : Root = new Root(new Child(root))
root: Root = Root@1f23418
scala> root.child.parent.child.parent
res0: Root = Root@1f23418
Cheers,
Miles
--
Miles Sabin
tel: +44 7813 944 528
gtalk: mi...@milessabin.com
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin
http://scala-scales.googlecode.com/svn/sites/snapshots/scales/scales-xml_2.9.0-1/0.0.1/doc/index.html#scales.utils.Tree
http://scala-scales.googlecode.com/svn/sites/snapshots/scales/scales-xml_2.9.0-1/0.0.1/doc/index.html#scales.utils.Path
Is a very good immutable structure / technique for handling immutable trees.
The only issue is to get to a child you have to go via each parent.
There are lots of easy to follow examples on the internet about
zippers, if Scales Xml's usage or Scalazs isn't appropriate for you.
https://github.com/nuttycom/scala-exercises/blob/master/solutions/Twins.scala
Kris
There is a wiki entry on uniqueness types.
http://en.wikipedia.org/wiki/Uniqueness_type
(See also the Clean programming language).
- --
Tony Morris
http://tmorris.net/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAk4zwvsACgkQmnpgrYe6r61QcgCcDkKTc6O+A9VFrP6IfYA4i9Yh
XLkAn0yXyfFaYfnAJRcU6QYehzvbAh++
=9wYW
-----END PGP SIGNATURE-----
This seems awfully weird and un-intuitive because you are not familiar
with the scala's by-name parameters. (=> root) is a by-name parameter,
it will not be evaluated when invoking the constructor, it will be
evaluated later, when it is accessed.
Scala does not mutate vals or put vals in scope before they are
initialized. What you see is a combination of deferred evaluation
using by-name parameter (not deferred immutability) and a lazy val,
which is initialized the first time it is accessed. Both by name
parameters and lazy vals are the standard Scala features, so there are
no hacks or any compiler magic involved.
class Node(name: String, children: List[Node])
Randall Schulz
> val root : Root = null
> root = new Root(new Child(=> root)) <--- oops we have to mutate the val now
> because it is accessible before it is initialized!
> I suppose for whatever reasons Scala puts a val in scope before it is
> initialized. Seems awfully weird and un-intuitive to me, but I guess it
> does allow some interesting hacks with cyclic lists that "look" like there's
> no mutation going on by deferring their immutability a little bit. Maybe
> that is why they allow this?
Scala does not mutate vals or put vals in scope before they are
initialized.
What you see is a combination of deferred evaluation
using by-name parameter (not deferred immutability) and a lazy val,
which is initialized the first time it is accessed. Both by name
parameters and lazy vals are the standard Scala features, so there are
no hacks or any compiler magic involved.
On 31/07/11 13:00, Dobes Vandermeer wrote:Then you would understand the termination semantics under certain
> I understand the use of deferred evaluation and by-name parameters
conditions of mutual recursion for different evaluation strategies
Scala is strict by default, which
carries implications for termination -- there is no "hack".
Java does similar (see vmspec around section 5 iirc):
On Jul 31, 2011 6:00 AM, "Dobes Vandermeer" <dob...@gmail.com> wrote:
>
> On Sun, Jul 31, 2011 at 11:06 AM, Tony Morris <tonym...@gmail.com> wrote:
>>
>> On 31/07/11 13:00, Dobes Vandermeer wrote:
>> > I understand the use of deferred
>
Snip, as others answered the rest and this may be of interest to others...
>
>
> I suspect this technique should probably also be avoided on the basis of its memory/performance implications. Presumably the lazy val technique creates one or more additional objects and classes as part of its implementation, whereas using a "var" would just create a regular java field.
>
It's written in many other places but worth repeating: lazy vals add a single volatile int to an instance. Performance wise this forces the smallest possible overhead for thread safety of that evaluation.
That int is shared for all lazy vals in that instance, which is pretty cool.
That said if you are using lazy vals to cache results in a presumed hotspot make sure the calculation is far slower than the lookup (by profiling it). By the same token if the call would be fast enough to repeat via a def then you will save on both the int and resulting vals memory usage.
I had exactly that issue when profiling and performance tweaking (memory and cpu) Scales Xml. Swapping lazy vals for defs brought a reduction of 30Mb for a 12Mb raw xml and a speed up of 8-10%. That speed increase is important in an xml parser but might not be for another given application.
Either way, rule of thumb (as ever) is to profile and see if it really is a problem. Lazy vals have a great semantic and shouldn't be dismissed unless they are a proven issue for your code.