gpt4 book ai didi

scala - 将 Scala 字符串转换为 StringContext 并虚拟转发引用

转载 作者:行者123 更新时间:2023-12-04 05:25:17 24 4
gpt4 key购买 nike

在 Scala 2.10.0-RC1 中有一个很棒的特性,String Interpolation .

这像这样工作:

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
}

这不起作用,因为实际上是前向引用。我可以写 xlazy val ,但编译器移动 x并将其用于 y可用。但是对于我的 DSL 设计,顺序是 yx必须保存!

到目前为止,我的解决方案是一个闭包,如下所示:
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"..."),它解决了 $ -引用。但到目前为止我一无所获,如何转换这个。总之我怎么投 "foo $x bars"foo $x bar" ?

什么我 found就是,如何个性化 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

另一个想法是一个不那么“嘈杂”的 lambda 符号,但我怎么能写出类似(或类似)这样的东西:
++ txt => s"""... ${Main.fig.number} ..."""

这样的符号是合理的。我不一定要编写自己的带有引用解析的字符串解析器。有人有偷偷摸摸的想法吗?

DSL api 在语义上是这样构建的:
object ++ {
def txt (s: String) = ...
}

最佳答案

来自 this question 的想法和解决方案,一个可能的解决方案如下(可在 Scala 2.10.0-RC2 上运行):

implicit def byname_to_noarg[A](a: => A) = () => a

case class StringContext(parts: String*) {
def $ (args: (() => Any)*) = () => {
val unpacked = args.map(a => a())
scala.StringContext(parts: _*).s(unpacked: _*)
}
}

class A {
def meth = "A's result"
}

object X {
val y = $"foo $x bar ${z.meth}. Forward reference solved."
val x = 3
val z = new A
}

// Execute
X.y()

谢谢你,雷克斯·克尔! :)

关于scala - 将 Scala 字符串转换为 StringContext 并虚拟转发引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13270906/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com