代码之家  ›  专栏  ›  技术社区  ›  Jeff

为什么这些语句中的一个用scala编译,而另一个用scala编译呢?

  •  2
  • Jeff  · 技术社区  · 16 年前

    ( 注释 :我在这里使用的是scala 2.7.7,而不是2.8)。

    我正在做一些非常简单的事情——基于一个简单的两列csv文件中的值创建一个映射——我已经很容易地完成了它,但是我很困惑为什么我的第一次尝试没有编译。代码如下:

    // Returns Iterator[String]
    private def getLines = Source.fromFile(csvFilePath).getLines
    
    // This doesn't compile:
    def mapping: Map[String,String] = {
        Map(getLines map { line: String =>
              val pairArr = line.split(",")
              pairArr(0) -> pairArr(1).trim()
            }.toList:_*)
      }
    
    // This DOES compile
    def mapping: Map[String,String] = {
        def strPair(line: String): (String,String) = {
          val pairArr = line.split(",")
          pairArr(0) -> pairArr(1).trim()
        }
        Map(getLines.map( strPair(_) ).toList:_*)
      }
    

    编译器错误是

    csvreader.scala:16: 错误:值ToList不是的成员 (ST环)=>(java.lang.st ring, Java.Lang.Script) 原因:可能缺少分号 在“value tolist”之前?[未经证实]
    }.tolist:*)[scalac]^
    [SCALAC]发现一个错误

    那又有什么好处呢?除了显式函数定义(与非工作示例中的anonymous相比)和()与{}之外,它们似乎应该与我等价。如果在非工作示例中将大括号替换为圆括号,则错误为“;”应为,但找到“val”。但是,如果删除局部变量定义并将字符串拆分两次并使用括号而不是大括号,则会编译。有人能给我解释一下这个区别吗,最好是用scala文档的链接来解释parens和花括号在用于包围方法参数时的区别?

    2 回复  |  直到 16 年前
        1
  •  4
  •   Ben Lings    16 年前

    看起来区别在于您在第一个示例中使用了运算符表示法。如果添加一组额外的圆括号,则可以:

    def mapping: Map[String,String] = {
        Map((getLines map { line: String =>
          val pairArr = line.split(",")
          pairArr(0) -> pairArr(1).trim()
        }).toList:_*)
    }
    

    或者不使用运算符语法

    def mapping: Map[String,String] = {
        Map(getLines.map({ line: String =>
          val pairArr = line.split(",")
          pairArr(0) -> pairArr(1).trim()
        }).toList:_*)
    }
    

    我认为问题在于,对于方法调用,使用常规方法调用语法比使用运算符语法具有更高的优先级。这意味着 .toList 正在应用于匿名函数,而不是应用于 map 方法调用。

        2
  •  2
  •   Justin Ardini    16 年前

    如果不使用运算符语法,则可以编译:

    //Compiles
    def mapping: Map[String,String] = {
        Map(getLines.map { line: String =>
              val pairArr = line.split(",")
              pairArr(0) -> pairArr(1).trim()
            }.toList:_*)
      }
    

    如何使用匿名函数没有问题,但是正如ben提到的,调用的语法 map 没有 . 不等同于典型的Java风格方法调用。

    推荐文章