【问题标题】:Actual precedence for infix operators in ScalaScala中中缀运算符的实际优先级
【发布时间】:2011-11-28 22:55:15
【问题描述】:

2011 年 5 月 24 日 Scala Language Specification 在第 6.12.3 节中发现了一个错字here。这是邮件列表中的acknowledged

中缀运算符的实际优先级是什么?

【问题讨论】:

    标签: scala operators


    【解决方案1】:

    我认为通过测试来弄清楚它会很有趣,我编写了以下代码以在 REPL 中执行。给定:

    val ops = List(
      "letter", "|", "^", 
      "&", "<", ">", "!", 
      "+", "-", "*", "/", "%", "?", 
      "=?", // add ? to prevent assignment
      ":?"  // add ? to prevent right-association
    )
    

    首先生成一个使用和测试运算符的中间 scala 文件。

    import java.io._
    
    // generate a class with all ops operators defined
    // where operator combines in a way we can figure out the precedence
    val methods = ops.map("""def %s(o: Op) = Op("["+o.v+v+"]")""".format(_))
    val body = methods.mkString("\n")
    val out = new PrintWriter(new FileWriter("Op.scala"))
    out.println("case class Op(v: String) {\n%s\n}".format(body))
    
    // generate tests for all combinations and store in comps
    // Op(".") op1 Op(".") op2 Op(".") v returns "[[..].]" when op2 > op1
    // returns "[.[..]]" when op1 <= op2
    def test(op1: String, op2:String) = {
      """("%s","%s") -> (Op(".") %s Op(".") %s Op(".")).v.startsWith("[[")""".
        format(op1, op2, op1, op2)
    }
    val tests = for (op1 <- ops; op2 <- ops) yield { test(op1, op2) }
    out.println("val comps = Map[(String, String), Boolean](%s)".format(
      tests.mkString(",\n")))
    out.close
    

    然后加载 Op 类,运行测试并加载 comps

    :load Op.scala
    
    // order operators based on tests
    val order = ops.sortWith((x,y) => comps(x -> y))
    
    // if op1 or op2 don't have higher precedence, they have the same precedence
    def samePrecedence(op1: String, op2: String) = 
      !comps(op1 -> op2) && !comps(op2 -> op1)
    
    def printPrecedenceGroups(list: List[String]): Unit = {
      if (list != Nil) {
        val (same, rest) = list.span(op => samePrecedence(op, list.head))
        println(same.mkString(" "))
        printPrecedenceGroups(rest)
      }
    }
    
    printPrecedenceGroups(order)
    

    打印出来:

    letter
    |
    ^
    &
    ! =?
    < >
    :?
    + -
    * / %
    ?
    

    所以与规范的主要区别是&lt; &gt;需要与= !切换。

    【讨论】:

      猜你喜欢
      • 2021-10-25
      • 2014-02-24
      • 2015-09-16
      • 2019-06-10
      • 2018-08-22
      • 2011-08-30
      • 2019-11-06
      • 2019-02-13
      • 2016-06-07
      相关资源
      最近更新 更多