Почему одно из этих утверждений компилируется в Scala, а не другое? - PullRequest
2 голосов
/ 02 апреля 2010

( Примечание : здесь я использую 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 не является членом (Святое кольцо) => (java.lang.String, java.lang.String) [scalac] возможно причина: возможно, точка с запятой отсутствует перед `значением toList '? [Scalac]
} .toList: _ *) [scalac] ^
[scalac] найдена одна ошибка

Так что же дает? Кажется, что они должны быть эквивалентны мне, кроме явного определения функции (против анонимного в нерабочем примере) и () против {}. Если я заменю фигурные скобки на круглые скобки в нерабочем примере, ошибка будет "';" ожидается, но 'val' найден. " Но если я удаляю определение локальной переменной и делю строку дважды И использую паренсы вместо фигурных скобок, он компилируется. Может ли кто-нибудь объяснить мне эту разницу, желательно со ссылкой на документы Scala, объясняющие разницу между паренсом и фигурными скобками, когда они используются для аргументов метода?

Ответы [ 2 ]

4 голосов
/ 02 апреля 2010

Похоже, разница в том, что вы используете обозначение оператора в первом примере. Если вы добавите дополнительный набор скобок, это сработает:

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 голосов
/ 02 апреля 2010

Если вы не используете синтаксис оператора, он прекрасно компилируется:

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

Нет проблем с использованием анонимной функции, но, как упоминал Бен, синтаксис вызовов map без . не эквивалентен типичному вызову метода в стиле Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...