com.thoughtworks.dsl.keywords

Members list

Concise view

Type members

Classlikes

trait AsynchronousIo[+Value] extends Trait

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.ReadFile

         import 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
         }

Tasks created from !-notation can be used in for-comprehension, and other keywords can be used together in the same for block. For example, the following cat function contains a single for block to concatenate file contents. It asynchronously iterates elements Seq, ArrayBuffer and String with the help of keywords.Each, managed native resources with the help of keywords.Using, performs previously created readAll task with the help of keywords.Shift, and finally converts the return type as a Task[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
Graph
Supertypes
trait Trait
class Any
Known subtypes
class Accept
class Connect
class Read
class ReadFile
class Write
class WriteFile

Attributes

Companion:
trait
Graph
Supertypes
class Object
trait Matchable
class Any
Self type
object Await

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Await.type
opaque object Each

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Each.type
object Fence extends Trait

Attributes

Graph
Supertypes
trait Trait
class Object
trait Matchable
class Any
Self type
Fence.type
final case class FlatMap[+Upstream, +Mapped](upstream: Upstream, flatMapper: () => Mapped) extends Trait

Attributes

Companion:
object
Graph
Supertypes
trait Serializable
trait Product
trait Equals
trait Trait
class Object
trait Matchable
class Any
object FlatMap

Attributes

Companion:
class
Graph
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
FlatMap.type
object Get

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Get.type

Attributes

Companion:
object
Graph
Supertypes
trait Serializable
trait Product
trait Equals
trait Trait
class Object
trait Matchable
class Any
object If

Attributes

Companion:
class
Graph
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
If.type
opaque object Match

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Match.type
object Monadic

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Monadic.type
object NoneSafe

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
object Pure

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Pure.type
object Put

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Put.type
object Return

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Return.type
opaque object Shift

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Shift.type
object Suspend

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Suspend.type

Attributes

Companion:
object
Graph
Supertypes
trait Serializable
trait Product
trait Equals
trait Trait
class Object
trait Matchable
class Any
opaque object TryCatch

Attributes

Companion:
class
Graph
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type

Attributes

Companion:
object
Graph
Supertypes
trait Serializable
trait Product
trait Equals
trait Trait
class Object
trait Matchable
class Any

Attributes

Companion:
class
Graph
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type

Attributes

Companion:
object
Graph
Supertypes
trait Serializable
trait Product
trait Equals
trait Trait
class Object
trait Matchable
class Any
object TryFinally

Attributes

Companion:
class
Graph
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
object Typed

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Typed.type
object Using

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Using.type

Attributes

Companion:
object
Graph
Supertypes
trait Serializable
trait Product
trait Equals
trait Trait
class Object
trait Matchable
class Any
object While

Attributes

Companion:
class
Graph
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
While.type
opaque object Yield

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Yield.type

Types

opaque type Await[+AwaitableValue]

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 with try / 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!"))
opaque type Each[+Element]

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))
opaque type Get[S]

Attributes

Authors:

杨博 (Yang Bo)

See also:
opaque type Monadic[+FA]

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.

Todo:

Monadic should be a scala.AnyVal after https://github.com/scala/bug/issues/10595 is resolved.

opaque type NoneSafe[+A]
opaque type Pure[+Value]
opaque type Put[+S]

Put is a Keyword to replace the value of the current context.

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 be O.

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")
opaque type Return[+ReturnValue]

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)

opaque type Shift[R, A]

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 of cont { 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")
   }
 }
opaque type Suspend[+Keyword]
opaque type Typed[+Keyword, +Value]

A type annotated keyword

A type annotated keyword

Attributes

opaque type Using[+R]

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:

dsl for usage of this Using keyword in continuations

opaque type Yield[+Element]

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 returns Seq[Element] or Seq[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"))

Value members

Concrete methods

def Each[Element](using dummyImplicit: DummyImplicit): Iterable[Element] =:= Each[Element]
def NoneSafe[A](using dummyImplicit: DummyImplicit): Option[A] =:= NoneSafe[A]
def Put[S](using dummyImplicit: DummyImplicit): S =:= Put[S]
def Shift[R, A](using dummyImplicit: DummyImplicit): R !! A =:= Shift[R, A]
def Using[R](using dummyImplicit: DummyImplicit): R =:= Using[R]
def Yield[Element](using dummyImplicit: DummyImplicit): Element =:= Yield[Element]