error: left- and right-associative operators with same precedence may not be mixed
error: left- and right-associative operators with same precedence may not be mixed
我正在尝试在 Scala 中制作 URI DSL,但中缀方法确实给我带来了麻烦。
即使在将冗长且非常不直观的优先级规则记入记忆之后,它们仍然给我带来麻烦。
class Foo {
def `://`(a: Unit) = this
def `:`(b: Unit) = this
}
object Foo {
def main(args: Array[String]): Unit = {
new Foo `://` {} `:` {}
}
}
产量
left- and right-associative operators with same precedence may not be mixed
new Foo `://` {} `:` {}
^
这是什么意思?我以为所有运算符都是左关联的。
有什么方法可以让我写出像这样的 DSL 吗?
"https" `://` "example.com" `:` 80
您选择的运营商名称有两个问题:
- 名称
://
包含双斜杠,因此如果没有反引号,编译器可能会将其误解为注释
- Name
:
因为所有其他以 :
结尾的运算符创建右关联运算符,这对于像 ::
或 #::
这样的运算符从头开始构建序列很方便.具有不同关联性的运算符在没有括号的情况下是不允许的,因为不清楚应该从哪里开始构建表达式。
所以我的建议是去掉双斜杠和冒号结尾,这可能会造成一些混乱,但正确的 DSL 语法:
object URILanguage extends App {
case class URL(protocol: String, hostname: String, port: Option[Int] = None, path: Seq[String] = Nil) {
def %(port: Int) = copy(port = Some(port))
def /(component: String) = copy(path = path :+ component)
}
implicit class WithHostname(protocol: String) {
def ~(hostname: String) = URL(protocol, hostname)
}
println("http" ~ "example.com" % 8080 / "mysite" / "index.html")
}
来自 The Scala Language Specification,第 6.12.3 节:
The associativity of an operator is determined by the operator’s last
character. Operators ending in a colon ‘:’ are right-associative. All
other operators are left-associative
编译器不知道是否将您的代码解释为:
80.`:`("https".`://`("example.com"))
或者这个:
"https".`://`(80.`:`("example.com"))
我认为没有办法阻止“:”被视为右结合运算符。您可以通过使用括号来帮助编译器;否则,您必须更改您的运营商名称。
我正在尝试在 Scala 中制作 URI DSL,但中缀方法确实给我带来了麻烦。
即使在将冗长且非常不直观的优先级规则记入记忆之后,它们仍然给我带来麻烦。
class Foo {
def `://`(a: Unit) = this
def `:`(b: Unit) = this
}
object Foo {
def main(args: Array[String]): Unit = {
new Foo `://` {} `:` {}
}
}
产量
left- and right-associative operators with same precedence may not be mixed
new Foo `://` {} `:` {}
^
这是什么意思?我以为所有运算符都是左关联的。
有什么方法可以让我写出像这样的 DSL 吗?
"https" `://` "example.com" `:` 80
您选择的运营商名称有两个问题:
- 名称
://
包含双斜杠,因此如果没有反引号,编译器可能会将其误解为注释 - Name
:
因为所有其他以:
结尾的运算符创建右关联运算符,这对于像::
或#::
这样的运算符从头开始构建序列很方便.具有不同关联性的运算符在没有括号的情况下是不允许的,因为不清楚应该从哪里开始构建表达式。
所以我的建议是去掉双斜杠和冒号结尾,这可能会造成一些混乱,但正确的 DSL 语法:
object URILanguage extends App {
case class URL(protocol: String, hostname: String, port: Option[Int] = None, path: Seq[String] = Nil) {
def %(port: Int) = copy(port = Some(port))
def /(component: String) = copy(path = path :+ component)
}
implicit class WithHostname(protocol: String) {
def ~(hostname: String) = URL(protocol, hostname)
}
println("http" ~ "example.com" % 8080 / "mysite" / "index.html")
}
来自 The Scala Language Specification,第 6.12.3 节:
The associativity of an operator is determined by the operator’s last character. Operators ending in a colon ‘:’ are right-associative. All other operators are left-associative
编译器不知道是否将您的代码解释为:
80.`:`("https".`://`("example.com"))
或者这个:
"https".`://`(80.`:`("example.com"))
我认为没有办法阻止“:”被视为右结合运算符。您可以通过使用括号来帮助编译器;否则,您必须更改您的运营商名称。