com.thoughtworks.dsl.keywords
Members list
Type members
Classlikes
The base keyword to perform asynchronous IO in domains.task.Tasks.
The base keyword to perform asynchronous IO in domains.task.Tasks.
Attributes
- Example:
The following
readAll
is a Task to read file content with the help of AsynchronousIo.ReadFileimport java.nio._, file._, channels._ import com.thoughtworks.dsl.domains.Task import com.thoughtworks.dsl.keywords._ import com.thoughtworks.dsl.keywords.Shift._ import com.thoughtworks.dsl.keywords.AsynchronousIo.ReadFile import scala.collection.mutable.ArrayBuffer import scala.io.Codec def readAll(channel: AsynchronousFileChannel, temporaryBufferSize: Int = 4096): Task[ArrayBuffer[CharBuffer]] = Task { val charBuffers = ArrayBuffer.empty[CharBuffer] val decoder = Codec.UTF8.decoder val byteBuffer = ByteBuffer.allocate(temporaryBufferSize) var position: Long = 0L while (!ReadFile(channel, byteBuffer, position) != -1) { position += byteBuffer.position() byteBuffer.flip() charBuffers += decoder.decode(byteBuffer) byteBuffer.clear() } charBuffers }
Task
s created from !-notation can be used infor
-comprehension, and other keywords can be used together in the samefor
block. For example, the followingcat
function contains a singlefor
block to concatenate file contents. It asynchronously iterates elementsSeq
,ArrayBuffer
andString
with the help of keywords.Each, managed native resources with the help of keywords.Using, performs previously createdreadAll
task with the help of keywords.Shift, and finally converts the return type as aTask[Vector[Char]]
.import com.thoughtworks.dsl._ import com.thoughtworks.dsl.keywords._ import com.thoughtworks.dsl.domains.Task import java.net.URL def cat(paths: Path*) = Each.ToView { for { path <- Each(paths) channel <- Using(AsynchronousFileChannel.open(path)) charBuffers <- Shift(readAll(channel)) charBuffer <- Each(charBuffers) char <- Each(charBuffer.toString) } yield char }.to[Task]
Then the
cat
function is used to concatenate files from this project, as shown below:Task.toFuture(Task { val filesToRead = for (fileName <- Seq(".sbtopts", ".scalafmt.conf")) yield { Paths.get(sourcecode.File()).getParent.resolve("../../../../../..").resolve(fileName) } (!Shift(cat(filesToRead: _*))).mkString should be( filesToRead.map { fileToRead => new String(Files.readAllBytes(fileToRead), io.Codec.UTF8.charSet) }.mkString ) })
- Companion:
- object
- Source:
- AsynchronousIo.scala
- Graph
- Supertypes
- trait Traitclass Any
- Known subtypes
Attributes
- Companion:
- trait
- Source:
- AsynchronousIo.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- AsynchronousIo.type
Attributes
- Source:
- Await.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Await.type
Attributes
- Source:
- Each.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Each.type
Attributes
- Source:
- Fence.scala
- Graph
- Supertypes
- Self type
- Fence.type
Attributes
- Companion:
- object
- Source:
- FlatMap.scala
- Graph
- Supertypes
Attributes
- Companion:
- class
- Source:
- FlatMap.scala
- Graph
- Supertypes
- Self type
- FlatMap.type
Attributes
- Source:
- Match.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Match.type
Attributes
- Source:
- Monadic.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Monadic.type
Attributes
- Source:
- NoneSafe.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- NoneSafe.type
Attributes
- Source:
- Pure.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Pure.type
Attributes
- Source:
- Return.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Return.type
Attributes
- Source:
- Shift.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Shift.type
Attributes
- Source:
- Suspend.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Suspend.type
Attributes
- Companion:
- object
- Source:
- TryCatch.scala
- Graph
- Supertypes
Attributes
- Companion:
- class
- Source:
- TryCatch.scala
- Graph
- Supertypes
- Self type
- TryCatch.type
Attributes
- Companion:
- object
- Source:
- TryCatchFinally.scala
- Graph
- Supertypes
Attributes
- Companion:
- class
- Source:
- TryCatchFinally.scala
- Graph
- Supertypes
- Self type
- TryCatchFinally.type
Attributes
- Companion:
- object
- Source:
- TryFinally.scala
- Graph
- Supertypes
Attributes
- Companion:
- class
- Source:
- TryFinally.scala
- Graph
- Supertypes
- Self type
- TryFinally.type
Attributes
- Source:
- Typed.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Typed.type
Attributes
- Source:
- Using.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Using.type
Attributes
- Companion:
- object
- Source:
- While.scala
- Graph
- Supertypes
Attributes
- Companion:
- class
- Source:
- While.scala
- Graph
- Supertypes
- Self type
- While.type
Attributes
- Source:
- Yield.scala
- Graph
- Supertypes
- class Objecttrait Matchableclass Any
- Self type
- Yield.type
Types
Await is a Keyword to extract value from a scala.concurrent.Future.
Await is a Keyword to extract value from a scala.concurrent.Future.
This keyword is available in functions whose return types are
Future, domains.task.Task, or any exception
aware continuations as (_ !! Throwable !! _)
.
Attributes
- Authors:
杨博 (Yang Bo)
- Example:
Given a Future:
import com.thoughtworks.dsl.macros.Reset.Default.* import scala.concurrent.Future val myFuture40 = Future { 40 }
You can Await the Future in another Future
def myFuture42 = *[Future] { !Await(myFuture40) + 2 }
A Future can be converted to a domains.task.Task with the help of Await.
import com.thoughtworks.dsl.domains.Task import com.thoughtworks.dsl.keywords.Await val myTask = Task { !Await(myFuture42) }
Then a domains.task.Task can be converted back to a scala.concurrent.Future via domains.task.Task.toFuture.
val myAssertionTask = Task { !Shift(myTask) should be(42) } Task.toFuture(myAssertionTask)
!Await
can be used together withtry
/catch
/finally
.import scala.concurrent.Future import com.thoughtworks.dsl.macros.Reset.Default.* val buffer = new StringBuffer def recoverFuture = Future { buffer.append("Oh") } def exceptionalFuture = Future[StringBuffer] { throw new IllegalStateException("No") } def myFuture = *[Future] { try { !Await(exceptionalFuture) } catch { case e: IllegalStateException => !Await(recoverFuture) buffer.append(' ') buffer.append(e.getMessage) } finally { buffer.append("!") } } myFuture.map(_.toString should be("Oh No!"))
Other keywords, including Return or Get, can be used together with Await
import scala.concurrent.Future import com.thoughtworks.dsl.keywords.{Get, Return} import com.thoughtworks.dsl.macros.Reset.Default.* val buffer = new StringBuffer def recoverFuture = Future { buffer.append("Oh") } def exceptionalFuture = Future[StringBuffer] { throw new IllegalStateException("No") } def myFuture = reset[Char => Future[StringBuffer]](!Return { try { !Await(exceptionalFuture) } catch { case e: IllegalStateException => !Await(recoverFuture) buffer.append(!Get[Char]) buffer.append(e.getMessage) } finally { buffer.append("!") } }) myFuture(' ').map(_.toString should be("Oh No!"))
- Source:
- Await.scala
Iterates though each element in elements.
Iterates though each element in elements.
Attributes
- Authors:
杨博 (Yang Bo)
- See also:
Dsl.For if you want to use traditional
for
comprehension instead of !-notation.- Example:
Each keywords can be used to calculate cartesian product.
import com.thoughtworks.dsl.macros.Reset.Default.* def cartesianProduct = reset (List(!Each(Array(1, 2, 3)) * !Each(Vector(1, 10, 100, 1000)))) cartesianProduct should be(List(1, 10, 100, 1000, 2, 20, 200, 2000, 3, 30, 300, 3000))
- Source:
- Each.scala
A keyword for extracting monadic value from the monadic expression fa.
A keyword for extracting monadic value from the monadic expression fa.
Attributes
- See also:
com.thoughtworks.dsl.domains.cats for using this Monadic keyword with cats.Monad.
com.thoughtworks.dsl.domains.scalaz for using this Monadic keyword with scalaz.Monad.
- Todo:
Monadic should be a scala.AnyVal after https://github.com/scala/bug/issues/10595 is resolved.
- Source:
- Monadic.scala
Attributes
- Source:
- NoneSafe.scala
Attributes
- Source:
- Pure.scala
Put is a Keyword to replace the value of the current context.
Purely functional programming languages usually do not support native first-class mutable variables. In those languages, mutable states can be implemented in state monads.
Put and Get are the Dsl-based replacements of state monads.
We use unary function as the domain of mutable state. The parameter of the unary function can be read from the Get keyword, and changed by the Put keyword.
Attributes
- Authors:
杨博 (Yang Bo)
- See also:
- Example:
The following example creates a function that accepts a string parameter and returns the upper-cased last character of the parameter.
import com.thoughtworks.dsl.macros.Reset.Default.reset def upperCasedLastCharacter = reset[String => Char] { val initialValue = !Get[String] !Put(initialValue.toUpperCase) val upperCased = !Get[String] Function.const(upperCased.last) }
For example, given a string of
foo
, the upper-cased last character should beO
.upperCasedLastCharacter("foo") should be('O')
Put and Get support multiple states. The following code creates a formatter that Put parts of content into a
Vector[Any]
of string buffers.import com.thoughtworks.dsl.macros.Reset.Default.reset def formatter = reset[Double => Int => Vector[Any] => String] { !Put(!Get[Vector[Any]] :+ "x=") !Put(!Get[Vector[Any]] :+ !Get[Double]) !Put(!Get[Vector[Any]] :+ ",y=") !Put(!Get[Vector[Any]] :+ !Get[Int]) !Return((!Get[Vector[Any]]).mkString) } formatter(0.5)(42)(Vector.empty) should be("x=0.5,y=42")
- Source:
- Put.scala
A Dsl.Keyword to early return a lifted value from the enclosing function.
A Dsl.Keyword to early return a lifted value from the enclosing function.
Attributes
- Authors:
杨博 (Yang Bo)
- Source:
- Return.scala
A keyword that extracts the value from a domains.Continuation.
A keyword that extracts the value from a domains.Continuation.
Attributes
- Authors:
杨博 (Yang Bo)
- Note:
This Shift keyword includes special treatment for exception handling and stack safety. Always use
Shift(cont).cpsApply { x => ... }
instead ofcont { x => ... }
to register a handler for the continuation, otherwise exception might be uncaught or stack might overflow.- Example:
Given a continuation whose type is
Unit !! Throwable !! Int
, it is considered as having an exception handler. When an exception is thrown,import scala.util.control.TailCalls.TailRec type !![R, +A] = (A => R) => R val cont: Unit !! Throwable !! Int = _ { if (System.nanoTime() > 0) { throw new Exception("my-exception") } else { 42 } }
Then
cpsApply
should catch the exception:Shift(cont).cpsApply[Unit !! Throwable] { i: Int => (failureHandler: Throwable => Unit) => fail("unreachable code") } { e: Throwable => e.getMessage should be("my-exception") }
However,
cont.apply
does not catch the exception:an[Exception] should be thrownBy { cont.apply { i => failureHandler => fail("unreachable code") } { e => e.getMessage should be("my-exception") } }
- Source:
- Shift.scala
Attributes
- Source:
- Suspend.scala
A type annotated keyword
This Using keyword automatically manage resources in
scala.concurrent.Future, domains.task.Task, and other asynchronous
domains derived from Future
or Task
.
This Using keyword automatically manage resources in
scala.concurrent.Future, domains.task.Task, and other asynchronous
domains derived from Future
or Task
.
Attributes
- Authors:
杨博 (Yang Bo)
- See also:
- Source:
- Using.scala
Attributes
- Authors:
杨博 (Yang Bo)
- See also:
comprehension if you want to use traditional
for
comprehension instead of !-notation.- Example:
This
Yield
keyword must be put inside a function that returnsSeq[Element]
orSeq[Element] !! ...
, or it will not compile.import com.thoughtworks.dsl.macros.Reset.Default.* "def f(): Int = !Yield(1)" shouldNot compile
Yield keywords can be used together with other keywords.
import com.thoughtworks.dsl.macros.Reset.Default.* def gccFlagBuilder(sourceFile: String, includes: String*) = reset[Stream[String]] { !Yield("gcc") !Yield("-c") !Yield(sourceFile) val include = !Each(includes) !Yield("-I") !Yield(include) Stream.empty } gccFlagBuilder("main.c", "lib1/include", "lib2/include") should be(Stream("gcc", "-c", "main.c", "-I", "lib1/include", "-I", "lib2/include"))
- Source:
- Yield.scala
Value members
Concrete methods
Attributes
- Source:
- Await.scala
Attributes
- Source:
- Each.scala
Attributes
- Source:
- Monadic.scala
Attributes
- Source:
- NoneSafe.scala
Attributes
- Source:
- Pure.scala
Attributes
- Source:
- Put.scala
Attributes
- Source:
- Return.scala
Attributes
- Source:
- Shift.scala
Attributes
- Source:
- Suspend.scala
Attributes
- Source:
- Typed.scala
Attributes
- Source:
- Using.scala
Attributes
- Source:
- Yield.scala