Я пытаюсь написать DSL со Scala.Сначала я хотел бы иметь возможность писать такие вещи, как
defType "foo"
при его использовании.
Я думал, что должно работать следующее:
src / main / scala / Test.scala
class Dsl {
def defType(name: String) = "dummy"
}
object Dsl {
def apply() = new Dsl()
}
class UseDsl {
def foo() = {
val dsl = Dsl()
import dsl._
dsl defType "foo"
defType("foo")
defType "foo"
}
}
Это не компилируется:
[error] Test.scala:15:17: ';' expected but string literal found.
[error] defType "foo"
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
Явное указание dsl
работает с пробелами для разделения имен методов и аргументов.
Неявное использование dsl
и скобок для указания аргументов против имен методов работает.
Попытка использовать их вместе не удалась.
Есть ли способ заставить это работать?
Как только это заработает, я планирую расширить DSL для поддержки таких вещей, как
defType "foo"
-- "bar1" :: "quz"
-- "bar2" :: "quz"
, что эквивалентно
dsl.defType("foo").
--(ImplicitClass("bar1", dsl).::("quz")).
--(ImplicitClass("bar2", dsl).::("quz"))
Это то, что я смогу заставить работать?Я думаю, что ImplicitClass
будет работать с декларацией вроде
def implicit ImplicitClass(a: String, implicit dsl: Dsl) = ...
, но ясно, что мое понимание того, как вы можете заставить Scala добавлять элементы в ваш код, несовершенно.
Если оно выиграетне работает, каковы некоторые минимальные дополнения, которые позволят ему работать?
build.sbt
ThisBuild / organization := "test"
ThisBuild / version := "0.0.1-SNAPSHOT"
ThisBuild / scalaVersion := "2.12.8"
//
// Projects
//
lazy val root = (project in file("."))