A scala DSL technique - collecting Subscribe

Consolidated older post - originally posted in Aug, 2011

When coming up with a scala internal DSL, it is often that one will come up with constructs that produce things that need collected, in a list, tree or similar.

For instance, instructions for a robot:

$if (condition) {

  move(1) :: move(2) :: move(3) :: Nil

  move(1) + move(2) + move(3)

  }

Due to syntax restrictions, it is often that people use operators to chain these, like the overloaded + above.

There is a technique you can use to make this look more familiar:

$if (condition) {

  move(1)

  move(2)

  move(3)

  }

While not the nicest, the idea is to use a static collector and collect the actions in there. You'll need levels, so that collecting nested blocks don't interfere, so there is a stack of collectors. Also, these collectors need to be thread-local so that different collecting threads don't interfere.

A reusable collector is in DslCollector.scala and a sample in DslCollectorTest.scala.

For this pattern, you have a Collector, a Collectable and the actual constructs:

  case class move(i: Int) extends DslCollectable

  def test1 = expect(move(1) :: move(2) :: Nil) {

    val collected = new collection.mutable.ListBuffer[Any]()

    DslCollector.collect { collected += _ }(1) { // start a collector level

      move(1) //collects itself

      move(2) //collects itself

    } // collector ends

    collected

  }

You can then embedd this in a higher-level construct of your DSL, like the $if used in the example, see this and this for the concrete code.

Enjoy!

By: Razie | 2014-06-25 .. 2016-05-11 | Tags: post , scala , dsl , pattern , programming |


See more in: Cool Scala Subscribe

Viewed 904 times ( | Print ) this page.


This content is Copyrighted, all rights reserved.

You need to log in to post a comment!