summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2010-01-18 14:53:54 +0000
committerMartin Odersky <odersky@gmail.com>2010-01-18 14:53:54 +0000
commit1184fd68b0bddeaf20b3a7de55d4be2efce61410 (patch)
treecab1da374005995c275d74382a4165c547764393 /src/library
parent0d5d440a68342296eed0474cf697f0c2cb085387 (diff)
downloadscala-1184fd68b0bddeaf20b3a7de55d4be2efce61410.tar.gz
scala-1184fd68b0bddeaf20b3a7de55d4be2efce61410.tar.bz2
scala-1184fd68b0bddeaf20b3a7de55d4be2efce61410.zip
cleaned up explicit tailcalls
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/util/control/TailCalls.scala56
-rw-r--r--src/library/scala/util/control/TailRec.scala24
2 files changed, 56 insertions, 24 deletions
diff --git a/src/library/scala/util/control/TailCalls.scala b/src/library/scala/util/control/TailCalls.scala
new file mode 100644
index 0000000000..59e9618028
--- /dev/null
+++ b/src/library/scala/util/control/TailCalls.scala
@@ -0,0 +1,56 @@
+package scala.util.control
+
+/** Methods exported by this object implement tail calls via trampolining.
+ * Tail calling methods have to return their result using `done` or call the next
+ * method using `tailcall`. Both return a `TailRec` object. The result of evaluating
+ * a tailcalling function can be retrieved from a `Tailrec` value using method result`.
+ * Here's a usage example:
+ * {{{
+ * import scala.util.control.TailCalls._
+ *
+ * def isEven(xs: List[Int]): TailRec[Boolean] =
+ * if (xs.isEmpty) done(true) else tailcall(isOdd(xs.tail))
+ *
+ * def isOdd(xs: List[Int]): TailRec[Boolean] =
+ * if (xs.isEmpty) done(false) else tailcall(isEven(xs.tail))
+ *
+ * isEven((1 to 100000).toList).result
+ * }}}
+ */
+object TailCalls {
+
+ /** This class represents a tailcalling computation.
+ */
+ abstract class TailRec[+A] {
+ /** Returns the result of the tailcalling computation
+ */
+ def result: A = {
+ def loop(body: TailRec[A]): A = body match {
+ case Call(rest) => loop(rest())
+ case Done(result) => result
+ }
+ loop(this)
+ }
+ }
+
+ /** Internal class representing a tailcall */
+ protected case class Call[A](rest: () => TailRec[A]) extends TailRec[A]
+
+ /** Internal class representing the final result return from a tailcalling computation */
+ protected case class Done[A](override val result: A) extends TailRec[A]
+
+ /** Performs a tailcall
+ * @param rest the expression to be evaluated in the tailcall
+ * @return a `TailRec` object representing the expression `rest`
+ */
+ def tailcall[A](rest: => TailRec[A]): TailRec[A] = new Call(() => rest)
+
+ /** Used to return final result from tailcalling computation
+ * @param `result` the result value
+ * @return a `TailRec` object representing a computation which immediately returns `result`
+ */
+ def done[A](result: A): TailRec[A] = new Done(result)
+
+}
+
+
diff --git a/src/library/scala/util/control/TailRec.scala b/src/library/scala/util/control/TailRec.scala
deleted file mode 100644
index db6cbfa2ed..0000000000
--- a/src/library/scala/util/control/TailRec.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package scala.util.control
-
-abstract class TailRec[+A]
-
-object TailRec {
-
- case class Call[A](rest: () => TailRec[A]) extends TailRec[A]
- case class Done[A](result: A) extends TailRec[A]
-
- def tailcall[A](rest: => TailRec[A]) = new Call(() => rest)
- def done [A](result: A) = new Done(result)
- def trampoline[A](body: TailRec[A]): A = {
- def loop(body: TailRec[A]): A = body match {
- case Call(rest) => loop(rest())
- case Done(result) => result
- }
- loop(body)
- }
- def loop[A](body: TailRec[A]): A = body match {
- case Call(rest) => loop[A](rest())
- case Done(result) => result
- }
-}
-