Scala 2.10.0-RC1には、文字列補間というすばらしい機能があります。
これは次のように機能します。
scala> val x = 1
x: Int = 1
scala> val y = s"Interpolated String $x"
y: String = Interpolated String 1
しかし、私はScalaを使用して内部DSLを構築しているため、一種の前方参照で処理する必要があります。あなたが念頭に置いていること、DSLはどのように見えるか(それはドキュメント生成用です):
object Main {
§ > "Heading"
§ >> "Subheading"
++ txt """
Lorem ipsum Abb. ${Main.fig.number} dolor sit amet, consetetur sadipscing elitr, sed diam
nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
sed diam voluptua.
"""
val fig =
++ figure(
src="https://...",
desc="example figure"
)
}
しかし、問題は意味的に次のようになります。
object X {
val y = s"$x with reverse reference"
val x = 3
}
そして、これは事実上前方参照のために機能しません。x
として書くことはできますlazy val
が、コンパイラが移動x
して利用できるようにしy
ます。しかし、私のDSL設計では、順序をy
維持するx
必要があります。
これまでのところ、私の解決策は次のようなクロージャです。
object X {
val y = () => s"$x with reverse reference"
val x = 3
}
これにより、すべての変数が使用可能X.y()
になったときに、最後に呼び出すことができます。しかし、欠点は、「醜い」ということです。ドメインユーザーはこの種の魔法を理解できません。ドメインユーザーは次のように記述する必要があります(ただし、機能します)。
++ txt (() => s"""
Lorem ipsum Abb. ${Main.fig.number} dolor sit amet, consetetur sadipscing elitr, sed diam
nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
sed diam voluptua.
""")
したがって、クロージャーマジックをDSL apiに移動するというアイデアですが、"$x with reverse reference"
通常どおりに渡しString
、最後にこの文字列をStringContext
(s "...")として解決する必要があります。これにより、$
-referencesが解決されます。しかし、これまでのところ、これをキャストする方法は何も見つかりませんでした。要するに、どうすればキャストでき"foo $x bar
ますs"foo $x bar"
か?
私が見つけたのは、どのように個別StringContext
化するかですが、これを私の問題にどのように使用できるかわかりません。
scala> case class StringContext(parts: String*) {
| def rr (args: Any*) = scala.StringContext(parts: _*).s(args: _*)
| }
defined class StringContext
scala> rr"hi"
res3: String = hi
scala> rr"hi $s"
res4: String = hi 1
もう1つのアイデアは、「ノイズの少ない」ラムダ表記ですが、次のような(または同様の)ものをどのように記述できますか。
++ txt => s"""... ${Main.fig.number} ..."""
そのような表記は合理的です。参照を解決する独自の文字列パーサーを作成する必要はありません。誰か卑劣な考え?
DSL APIは、セマンティック的に次のように構築されます。
object ++ {
def txt (s: String) = ...
}