Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A framework to create embedded Domain-Specific Languages in Scala

License

NotificationsYou must be signed in to change notification settings

ThoughtWorksInc/Dsl.scala

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Scala CIScaladexMaven CentralScaladocJoin the chat at https://gitter.im/ThoughtWorksInc/Dsl.scala

Dsl.scala is a framework to create embeddedDomain-SpecificLanguages in Scala. It can be considered as an alternative syntax to for comprehension, Scala Async and Scala Continuations. It unifies monads, generators, asynchronous functions, coroutines and continuations to a single universal syntax, and can be easily integrate to Scalaz, Cats, Scala Collections, Scala Futures, Akka HTTP, Java NIO, or your custom domains.

A DSL author is able to create language keywords by implementing theDsl trait, which contains only one abstract method to be implemented. No knowledge about Scala compiler or AST macros is required.

DSLs written inDsl.scala are collaborative with others DSLs and Scala control flows. A DSL user can create functions that contains interleaved DSLs implemented by different vendors, along with ordinary Scala control flows.

We also provide some built-in keywords, including:

  • TheAwait keyword for creating memoized asynchronous values as ScalaFutures, similar to theawait /async keywords in C#, Python and JavaScript.
  • TheShift keyword for creating asynchronous tasks as delimited continuations, similar to theshift operator inScala Continuations.
  • TheAsynchronousIo.Connect,AsynchronousIo.Accept,AsynchronousIo.Read andAsynchronousIo.Write keywords for performing I/O on an asynchronous channel.
  • TheYield keyword for generating lazy streams, similar toyield in C#, Python and JavaScript.
  • TheFork keyword for duplicating current context, similar to thefork system call in POSIX.
  • TheReturn keyword for early returning, similar to the nativereturn keyword in Scala.
  • TheUsing keyword to automatically close resources when exiting a scope, similar to the nativeusing keyword in C#.
  • TheMonadic keyword for creating Scalaz or Cats monadic control flow, similar to the !-notation in Idris.
  • TheNullSafe keyword for the null safe operator, similar to the? operator in Kotlin and Groovy.
  • TheNoneSafe keyword for theNone safe operator, similar to theMaybe monad in Haskell.

All the above keywords can be used together with each others. For example you can perform list comprehension to manipulate native resources in an asynchronous task by usingEach,Using andShift together.

Getting Started

Suppose you want to create a random number generator. The generated numbers should be stored in a lazily evaluated infinite stream, which can be built with the help of our built-in domain-specific keywordYield.

So, you need to add the library that contains the implementation of the keywordYield:

// Add the "keywords-yield" library in your build.sbt, to use the `Yield` keywordlibraryDependencies+="com.thoughtworks.dsl"%%"keywords-yield"%"latest.release"// Add other "keywords-xxx" libraries in your build.sbt, to use other keywords// libraryDependencies += "com.thoughtworks.dsl" %% "keywords-xxx" % "latest.release"

The random number generator can be implemented as a recursive function that produces the next random number in each iteration.

importcom.thoughtworks.dsl.keywords.Yield// Must not annotated with @tailrecdefxorshiftRandomGenerator(seed:Int):LazyList[Int]= reset {valtmp1= seed^ (seed<<13)valtmp2= tmp1^ (tmp1>>>17)valtmp3= tmp2^ (tmp2<<5)!Yield(tmp3)  xorshiftRandomGenerator(tmp3)}

Note that a keyword is a plain case class. You need a! prefix to the keyword to activate the DSL.

It's done. We can test it in ScalaTest:

valmyGenerator= xorshiftRandomGenerator(seed=123)myGenerator(0) should be(31682556)myGenerator(1) should be(-276305998)myGenerator(2) should be(2101636938)

The call toxorshiftRandomGenerator does not throw aStackOverflowError because the execution ofxorshiftRandomGenerator will be paused at the keywordYield, and it will be resumed when the caller is looking for the next number.

Showcases

(Feel free to add your project here)

Links and related works

Packages

No packages published

Contributors5

Languages


[8]ページ先頭

©2009-2025 Movatter.jp