Sök…


Anmärkningar

Värdet och variabla namn bör vara i mindre kamelfall

Ständiga namn bör vara i övre kamelfall. Det vill säga, om medlemmen är slutlig, oföränderlig och den tillhör ett paketobjekt eller ett objekt, kan det betraktas som en konstant

Metod, värde och variabla namn ska vara i mindre kamelfall

Källa: http://docs.scala-lang.org/style/naming-conventions.html

Denna sammanställning:

val (a,b) = (1,2)
// a: Int = 1
// b: Int = 2

men detta gör inte:

val (A,B) = (1,2)
// error: not found: value A
// error: not found: value B

Det är inte bara val kontra var

val och var

scala> val a = 123
a: Int = 123

scala> a = 456
<console>:8: error: reassignment to val
       a = 456

scala> var b = 123
b: Int = 123

scala> b = 321
b: Int = 321
  • val är oföränderliga: som en final variabel i Java kan du inte ändra den när den har initialiserats
  • var referenser kan överföras som en enkel variabel deklaration i Java

Oändliga och muterbara samlingar

  val mut = scala.collection.mutable.Map.empty[String, Int]
  mut += ("123" -> 123)
  mut += ("456" -> 456)
  mut += ("789" -> 789)

  val imm = scala.collection.immutable.Map.empty[String, Int]
  imm + ("123" -> 123)
  imm + ("456" -> 456)
  imm + ("789" -> 789)

  scala> mut
    Map(123 -> 123, 456 -> 456, 789 -> 789)

  scala> imm
    Map()

scala> imm + ("123" -> 123) + ("456" -> 456) + ("789" -> 789)
    Map(123 -> 123, 456 -> 456, 789 -> 789)

Scala standardbibliotek erbjuder både immutable och mutable datastrukturer, inte referensen till det. Varje gång en immutable datastruktur "modifieras" produceras en ny instans istället för att modifiera den ursprungliga samlingen på plats. Varje instans av samlingen kan dela betydande struktur med en annan instans.

Muterbar och oföränderlig samling (officiell Scala-dokumentation)

Men jag kan inte använda oföränderlighet i det här fallet!

Låt oss välja som exempel en funktion som tar 2 Map och returnerar en Map innehåller alla element i ma och mb :

def merge2Maps(ma: Map[String, Int], mb: Map[String, Int]): Map[String, Int]

Ett första försök kan vara att iterera genom elementen på en av kartorna med for ((k, v) <- map) och på något sätt returnera den sammanslagna kartan.

def merge2Maps(ma: ..., mb: ...): Map[String, Int] = {

  for ((k, v) <- mb) {
    ???
  }

}

Detta allra första drag lägger omedelbart en begränsning: en mutation utanför det for nu behövs . Detta är mer tydligt när av-socker av for :

// this:
for ((k, v) <- map) { ??? }

// is equivalent to:
map.foreach { case (k, v) => ??? }

"Varför måste vi mutera?"

foreach beror på biverkningar. Varje gång vi vill att något ska hända inom en foreach måste vi " foreach något", i det här fallet kan vi mutera ett variabelt var result eller så kan vi använda en muterbar datastruktur.

Skapa och fylla result

Låt oss anta att ma och mb är scala.collection.immutable.Map , vi kan skapa result Map från ma :

val result = mutable.Map() ++ ma

Sedan iterera igenom mb lägga till dess element och om key för det aktuella elementet på ma redan finns, låt oss åsidosätta det med mb ett.

mb.foreach { case (k, v) => result += (k -> v) }

Muterbart genomförande

Hittills så bra, vi "var tvungna att använda muterbara samlingar" och en korrekt implementering kan vara:

def merge2Maps(ma: Map[String, Int], mb: Map[String, Int]): Map[String, Int] = {
  val result = scala.collection.mutable.Map() ++ ma
  mb.foreach { case (k, v) => result += (k -> v) }
  result.toMap // to get back an immutable Map
}

Som förväntat:

scala> merge2Maps(Map("a" -> 11, "b" -> 12), Map("b" -> 22, "c" -> 23))
  Map(a -> 11, b -> 22, c -> 23)

Fälls till räddningen

Hur kan vi bli av med foreach i det här scenariot? Om allt vi ska göra är att iterera över samlingselementen och tillämpa en funktion medan du samlar resultatet på alternativet kan använda .foldLeft :

def merge2Maps(ma: Map[String, Int], mb: Map[String, Int]): Map[String, Int] = {
  mb.foldLeft(ma) { case (result, (k, v)) => result + (k -> v) }
  // or more concisely mb.foldLeft(ma) { _ + _ }
}

I detta fall vår "resultat" är det ackumulerade värdet med utgångspunkt från ma , det zero i .foldLeft .

Mellanresultat

Det är uppenbart att denna immutabla lösning producerar och förstör många Map under vikning, men det är värt att nämna att dessa instanser inte är en fullständig klon av den samlade Map utan istället delar betydande struktur (data) med den existerande instansen.

Enklare rimlighet

Det är lättare att resonera om det semantiska om det är mer deklarativt som .foldLeft metoden. Att använda immutable datastrukturer kan hjälpa till att göra vår implementering lättare att resonera med.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow