scalaadvanced
DSL Builder Pattern
Create type-safe domain-specific languages with Scala's builder pattern using apply and infix notation.
scalaPress ⌘/Ctrl + Shift + C to copy
import scala.collection.mutable.ListBuffer
// SQL-like DSL
case class Query(
table: String,
conditions: List[String] = Nil,
columns: List[String] = List("*"),
ordering: Option[String] = None,
limit: Option[Int] = None
):
def select(cols: String*): Query = copy(columns = cols.toList)
def where(condition: String): Query = copy(conditions = conditions :+ condition)
def orderBy(col: String): Query = copy(ordering = Some(col))
def limit(n: Int): Query = copy(limit = Some(n))
def toSQL: String =
val cols = columns.mkString(", ")
val base = s"SELECT $cols FROM $table"
val where_ = if conditions.nonEmpty then s" WHERE ${conditions.mkString(" AND ")}" else ""
val order = ordering.map(o => s" ORDER BY $o").getOrElse("")
val lim = limit.map(l => s" LIMIT $l").getOrElse("")
base + where_ + order + lim
def from(table: String): Query = Query(table)
// HTML DSL
class Element(val tag: String):
private val children = ListBuffer[String]()
private val attrs = ListBuffer[(String, String)]()
def attr(key: String, value: String): Element =
attrs += ((key, value)); this
def content(text: String): Element =
children += text; this
def child(elem: Element): Element =
children += elem.render; this
def render: String =
val attrStr = if attrs.nonEmpty then
" " + attrs.map((k, v) => s"""$k="$v"""").mkString(" ")
else ""
s"<$tag$attrStr>${children.mkString}</$tag>"
def div = Element("div")
def p = Element("p")
def h1 = Element("h1")
def a = Element("a")
def ul = Element("ul")
def li = Element("li")
// Config DSL
case class ServerConfig(
host: String = "localhost",
port: Int = 8080,
maxConnections: Int = 100,
ssl: Boolean = false,
routes: List[(String, String)] = Nil
)
class ServerBuilder:
private var config = ServerConfig()
def host(h: String): ServerBuilder = { config = config.copy(host = h); this }
def port(p: Int): ServerBuilder = { config = config.copy(port = p); this }
def maxConnections(n: Int): ServerBuilder = { config = config.copy(maxConnections = n); this }
def enableSSL: ServerBuilder = { config = config.copy(ssl = true); this }
def route(path: String, handler: String): ServerBuilder =
config = config.copy(routes = config.routes :+ (path, handler)); this
def build: ServerConfig = config
def server: ServerBuilder = ServerBuilder()
@main def run(): Unit =
// SQL DSL
val query = from("users")
.select("name", "email", "age")
.where("age > 18")
.where("active = true")
.orderBy("name ASC")
.limit(50)
println(query.toSQL)
// HTML DSL
val html = div.attr("class", "container").child(
h1.content("Welcome")
).child(
p.content("Hello, World!")
).child(
ul.child(
li.content("Item 1")
).child(
li.content("Item 2")
)
)
println(html.render)
// Config DSL
val cfg = server
.host("0.0.0.0")
.port(443)
.maxConnections(1000)
.enableSSL
.route("/api/users", "UserController")
.route("/api/orders", "OrderController")
.build
println(s"Server: ${cfg.host}:${cfg.port} (SSL=${cfg.ssl})")
cfg.routes.foreach((path, handler) => println(s" $path -> $handler"))Use Cases
- Type-safe query builders
- Configuration DSLs
- HTML/markup generation
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
scalaadvanced
Context Functions and Capability Pattern
Use Scala 3 context functions for dependency injection, capability passing, and builder DSLs.
Best for: Dependency injection without frameworks
#scala#context-functions
scalaintermediate
Custom Extractors with unapply
Create custom pattern matching extractors: unapply, unapplySeq, and boolean extractors.
Best for: Domain-specific pattern matching
#scala#extractors
scalaintermediate
Custom String Interpolation
Create custom string interpolators in Scala: SQL, HTML, JSON, and validated interpolation.
Best for: SQL query building with parameter binding
#scala#string-interpolation
kotlinadvanced
Type-Safe DSL Builder
Build domain-specific languages with Kotlin: receiver lambdas, @DslMarker, and nested builders.
Best for: Configuration DSLs for frameworks
#kotlin#dsl