For what it is worth, the equivalent Scala code is
trait Pong[T] {}
class Ping[T] extends Pong[Pong[X forSome { type X >: Ping[Ping[T]]}]] {
def Ping() {
val Ping : Pong[X forSome { type X >: Ping[Long]}] = new Ping[Long]();
}
}
which produces the errors
Test.scala:3: error: illegal cyclic reference involving class Ping
class Ping[T] extends Pong[Pong[X forSome { type X >: Ping[Ping[T]]}]] {
^
Test.scala:5: error: type mismatch;
found : Ping[Long]
required: Pong[X forSome { type X >: Ping[Long] }]
Note: Long <: X forSome { type X >: Ping[Long] }, but trait Pong is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
val Ping : Pong[X forSome { type X >: Ping[Long]}] = new Ping[Long]();
However, if you set the symbol locking depth larger (-Yrecursion n) you'll also get a stack overflow as well. So it isn't necessarily that Scala has an algorithmically better approach to subtyping. The symbol locking algorithm is more of a catchall...
And you can do precisely the same thing in C++ if you're willing to write somewhat non-trivial template code.
This kind of thing is more surprising to Java programmers, I daresay, because the idea compiling a program being Turing-complete is not covered in most Java programming courses.
(Problems are Turing-complete; languages are Turing-equivalent, if you ignore the fact the Universe is finite.)
Anyone have a non-terminating C compile? (Other than X11. I compiled that from scratch back in ancient times and it took a whole day. At least it seemed like it wasn't going to terminate.)
C doesn't support metaprogramming, unless you count the preprocessor language. With the preprocessor, you could have a couple files mutually #include each other...
Actually seems to be a bit more involved: according to the submitter[1] Java is trying to prove something that is undecidable on Java's current type system. To solve it you'd have to make it stricter.
Unfortunately, adding an occurs check here is not the right way to go. The possibility of an infinite loop is there for a reason (to make the generics more expressive) and adding an occurs check will make the language less expressive.
I don't see a problem with non-terminating compilation. It makes sense to add more power to the compiler, but it comes at a cost. The possibility of non-termination is not a huge price to pay for it. In practice, the recursion will never go very deep so a simple max recursion depth check is enough to keep the compiler from hogging cpu and memory.
while the compilation does technically terminate it is doing so with a StackOverflowError which along with the resulting stack-trace most likely indicates a non-terminating recursion.
It only terminates due to a finite limit on the size of the stack.
While I would never miss a chance to bash Java, it really looks like it's just a bug in the compiler. The input that triggers it is definitely not code that you see in production every day. I'm sure that it will be fixed eventually.
[+] [-] trurl|14 years ago|reply
[+] [-] trurl|14 years ago|reply
[+] [-] rayiner|14 years ago|reply
[+] [-] ced|14 years ago|reply
[+] [-] yxhuvud|14 years ago|reply
http://www.perlmonks.org/?node_id=663393
[+] [-] derleth|14 years ago|reply
This kind of thing is more surprising to Java programmers, I daresay, because the idea compiling a program being Turing-complete is not covered in most Java programming courses.
(Problems are Turing-complete; languages are Turing-equivalent, if you ignore the fact the Universe is finite.)
[+] [-] dill_day|14 years ago|reply
[+] [-] lell|14 years ago|reply
[+] [-] machrider|14 years ago|reply
[+] [-] malkia|14 years ago|reply
[+] [-] finnw|14 years ago|reply
If so, it should be a relatively easy fix.
[+] [-] DanielRibeiro|14 years ago|reply
[1] http://www.reddit.com/r/programming/comments/mlbna/scala_fee...
[+] [-] exDM69|14 years ago|reply
I don't see a problem with non-terminating compilation. It makes sense to add more power to the compiler, but it comes at a cost. The possibility of non-termination is not a huge price to pay for it. In practice, the recursion will never go very deep so a simple max recursion depth check is enough to keep the compiler from hogging cpu and memory.
[+] [-] lurker17|14 years ago|reply
[+] [-] andrewflnr|14 years ago|reply
[+] [-] spectre|14 years ago|reply
It only terminates due to a finite limit on the size of the stack.
[+] [-] kamkha|14 years ago|reply
[+] [-] cgag|14 years ago|reply
[+] [-] dekz|14 years ago|reply
[+] [-] kodablah|14 years ago|reply
[+] [-] michaelfeathers|14 years ago|reply
[+] [-] dodedo|14 years ago|reply
perl -wle'BEGIN {1 while 1}'
Heh.
[+] [-] pyre|14 years ago|reply
[+] [-] malkia|14 years ago|reply
#include "aux"
#include "con"
// And off course
#include __FILE__
[+] [-] DrJokepu|14 years ago|reply
[+] [-] kmm|14 years ago|reply
[+] [-] unknown|14 years ago|reply
[deleted]