com.thoughtworks.dsl.domains
Members list
Type members
Classlikes
Attributes
- Source:
- Continuation.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Continuation.type
Attributes
- Authors:
杨博 (Yang Bo)
- Source:
- Task.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Task.type
Contains interpreters to enable !-notation for Monadic and other keywords in code blocks whose type support scalaz.Bind, scalaz.MonadError and scalaz.MonadTrans.
Contains interpreters to enable !-notation for Monadic and other keywords in code blocks whose type support scalaz.Bind, scalaz.MonadError and scalaz.MonadTrans.
Attributes
- Authors:
杨博 (Yang Bo)
- Example:
scalaz.Free#Trampoline is a monadic data type that performs tail call optimization. It can be built from a
@[[Dsl.reset reset]]
code block within some !-notation, similar to the each method in ThoughtWorks Each.import _root_.scalaz.Trampoline import _root_.scalaz.Free.Trampoline import com.thoughtworks.dsl.keywords.Monadic import com.thoughtworks.dsl.domains.scalaz.given import com.thoughtworks.dsl.macros.Reset.Default.reset import com.thoughtworks.dsl.keywords.Monadic.unary_! val trampoline3 = Trampoline.done(3) def dslSquare = reset(Trampoline.delay { s"This string is produced by a trampoline: ${!trampoline3 * !trampoline3}" }) dslSquare.run should be("This string is produced by a trampoline: 9")
!trampoline3
is a shortcut of!Monadic(trampoline3)
, enabled byimport com.thoughtworks.dsl.keywords.Monadic.given
, which will be converted toflatMap
calls by our DSL interpreter. Thus, the methoddslSquare
is equivalent to the following code in scalaz.syntax:def scalazSyntaxSquare = trampoline3.flatMap { tmp1 => trampoline3.flatMap { tmp2 => Trampoline.delay { s"This string is produced by a trampoline: ${tmp1 * tmp2}" } } } scalazSyntaxSquare.run should be("This string is produced by a trampoline: 9")
A
@[[Dsl.reset reset]]
code block can containtry
/catch
/finally
if the monadic data type supports scalaz.MonadError. tryt.scala is a monad transformer that provides scalaz.MonadError, thereforetry
/catch
/finally
expressions can be used inside a@[[Dsl.reset reset]]
code block whose return type isTryT[Trampoline, ?]
.import com.thoughtworks.tryt.invariant.TryT, TryT.given import scala.util.{Try, Success} type TryTTransfomredTrampoline[A] = TryT[Trampoline, A] val trampolineSuccess0: TryTTransfomredTrampoline[Int] = TryT(Trampoline.done(Try(0))) def dslTryCatch: TryTTransfomredTrampoline[String] = reset(TryT(Trampoline.delay(Try { try { s"Division result: ${!trampoline3 / !trampolineSuccess0}" } catch { case e: ArithmeticException => s"Cannot divide ${!trampoline3} by ${!trampolineSuccess0}" } }))) inside(dslTryCatch) { case TryT(trampoline) => trampoline.run should be(Success("Cannot divide 3 by 0")) }
Note that !-notation can be used on both
trampoline3
andtrampolineSuccess0
even when they are different types, i.e.trampoline3
is a vanilla Trampoline, whiletrampolineSuccess0
is a TryT-transfomred Trampoline. It is possible because the interpreters of the keywords.Monadic invoke scalaz.MonadTrans.liftM automatically. The abovedslTryCatch
method is equivalent to the following code in scalaz.syntax:import _root_.scalaz.syntax.monad._ def scalazSyntaxTryCatch: TryTTransfomredTrampoline[String] = { import _root_.scalaz.syntax.monadError._ trampoline3.liftM[TryT].flatMap { tmp0 => trampolineSuccess0.flatMap { tmp1 => TryT(Trampoline.delay(Try(s"Division result: ${tmp0 / tmp1}"))) } }.handleError { case e: ArithmeticException => trampoline3.liftM[TryT].flatMap { tmp2 => trampolineSuccess0.flatMap { tmp3 => TryT(Trampoline.delay(Try(s"Cannot divide ${tmp2} by ${tmp3}"))) } } case e => e.raiseError[TryTTransfomredTrampoline, String] } } inside(scalazSyntaxTryCatch) { case TryT(trampoline) => trampoline.run should be(Success("Cannot divide 3 by 0")) }
- Source:
- scalaz.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- scalaz.type
Types
Attributes
- Source:
- Continuation.scala
The asynchronous task that supports exception handling, resource management, and is stack-safe.
The asynchronous task that supports exception handling, resource management, and is stack-safe.
Attributes
- Example:
A Task can be created from
for
-comprehension, where keywords.Each can be used together to asynchronously iterate collections. For example, the aboveconcatenateRemoteData
downloads and concatenates data from multiple URLs.import com.thoughtworks.dsl._ import com.thoughtworks.dsl.keywords._ import com.thoughtworks.dsl.domains.Task import java.net.URL def concatenateRemoteData(urls: List[URL], downloader: URL => Task[Vector[Byte]]) = Each.ToView { for { url <- Each(urls) data <- Shift(downloader(url)) byte <- Each(data) } yield byte }.to[Task]
A Task can be also created from Task.apply
def mockDownloader(url: URL) = Task { "mock data\n".getBytes.toVector }
A Task can be then converted to scala.concurrent.Future via Task.toFuture, in order to integrate into other frameworks. In this example, it's a
Future[Assertion]
required by org.scalatest.freespec.AsyncFreeSpec.val mockUrls = List(new URL("http://example.com/file1"), new URL("http://example.com/file2")) import org.scalatest.Assertion def assertion: Task[Assertion] = Task { new String((!Shift(concatenateRemoteData(mockUrls, mockDownloader))).toArray) should be("mock data\nmock data\n") } Task.toFuture(assertion)
- Source:
- Task.scala