2 Stimmen

Warum lässt sich eine dieser Anweisungen in Scala kompilieren, die andere aber nicht?

( Hinweis : Ich verwende hier Scala 2.7.7, nicht 2.8).

Ich tue etwas ziemlich einfach - Erstellen einer Karte basierend auf den Werten in einer einfachen, 2-Spalten-CSV-Datei - und ich habe es leicht genug abgeschlossen, aber ich bin perplex, warum mein erster Versuch nicht kompilieren. Hier ist der Code:

// 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:_*)
  }

Der Compilerfehler lautet

CsvReader. error: Wert toList ist kein Mitglied von (St ring) => (java.lang.String, java.lang.String) [scalac] möglich Ursache: vielleicht fehlt ein Semikolon vor `Wert toList'? [scalac]
}.toList:_*) [scalac] ^
[scalac] ein Fehler gefunden

Was ist also los? Sie scheinen mir äquivalent zu sein, abgesehen von der expliziten Funktionsdefinition (im Gegensatz zu anonymous in dem nicht funktionierenden Beispiel) und () im Gegensatz zu {}. Wenn ich im nicht funktionierenden Beispiel die geschweiften Klammern durch Klammern ersetze, lautet die Fehlermeldung "';' erwartet, aber 'val' gefunden." Entferne ich jedoch die Definition der lokalen Variablen und teile die Zeichenkette zweimal UND verwende Klammern anstelle der geschweiften Klammern, lässt sich das Programm kompilieren. Kann mir jemand diesen Unterschied erklären, vorzugsweise mit einem Link zu Scala-Dokumenten, die den Unterschied zwischen Parens und geschweiften Klammern erklären, wenn sie verwendet werden, um Methodenargumente zu umgeben?

4voto

Ben Lings Punkte 28080

Es sieht so aus, als ob der Unterschied darin besteht, dass Sie im ersten Beispiel die Operator-Notation verwenden. Wenn Sie einen zusätzlichen Satz von Klammern hinzufügen, funktioniert es:

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

oder wenn Sie die Operator-Syntax nicht verwenden, funktioniert es

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

Ich denke, das Problem ist, dass die normale Syntax für Methodenaufrufe Vorrang vor der Operator-Syntax für Methodenaufrufe hat. Dies bedeutete, dass die .toList auf die anonyme Funktion angewandt wurde und nicht auf das Ergebnis der map Methodenaufruf.

2voto

Justin Ardini Punkte 9530

Wenn Sie die Operator-Syntax nicht verwenden, lässt sich das Programm problemlos kompilieren:

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

Es gibt kein Problem damit, wie Sie die anonyme Funktion verwenden, aber wie Ben erwähnte, ist die Syntax der Aufrufe map ohne die . ist nicht gleichbedeutend mit dem typischen Methodenaufruf im Java-Stil.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X