Scala Cheatsheet

Scala Cheatsheet

Language

Podziękowania dla Brendan O’Connor. Ten cheatsheet ma być szybkim podsumowaniem konstrukcji składniowych Scali. Licencjonowany przez Brendan O’Connor pod licencją CC-BY-SA 3.0.

zmienne
var x = 5

Dobrze
x = 6
Zmienna.
val x = 5

Źle
x = 6
Stała.
var x: Double = 5
Zmienna z podanym typem.
funkcje
Dobrze
def f(x: Int) = { x * x }

Źle
def f(x: Int)   { x * x }
Definiowanie funkcji.
Ukryty błąd: bez znaku = jest procedurą zwracającą Unit; powoduje to chaos. Przestarzałe w Scali 2.13.
Dobrze
def f(x: Any) = println(x)

Źle
def f(x) = println(x)
Definiowanie funkcji.
Błąd składni: wymagane są typy dla każdego argumentu.
type R = Double
Alias typu.
def f(x: R)
vs.
def f(x: => R)
Wywoływanie przez wartość.

Wywoływanie przez nazwę (parametr leniwy).
(x: R) => x * x
Funkcja anonimowa.
(1 to 5).map(_ * 2)
vs.
(1 to 5).reduceLeft(_ + _)
Funkcja anonimowa: podkreślenie to argument pozycyjny.
(1 to 5).map(x => x * x)
Funkcja anonimowa: aby użyć argumentu dwa razy, musisz go nazwać
Dobrze
(1 to 5).map(2*)

Źle
(1 to 5).map(*2)
Funkcja anonimowa: związana metoda infiksowa. Możesz użyć także 2 * _.
(1 to 5).map { x =>
  val y = x * 2
  println(y)
  y
}
Funkcja anonimowa: z bloku zwracane jest ostatnie wyrażenie.
(1 to 5) filter {
  _ % 2 == 0
} map {
  _ * 2
}
Funkcja anonimowa: styl potokowy.
def compose(g: R => R, h: R => R) =
  (x: R) => g(h(x))

val f = compose(_ * 2, _ - 1)
Funkcja anonimowa: aby przekazać kilka bloków musisz użyć nawiasów.
val zscore =
  (mean: R, sd: R) =>
    (x: R) =>
      (x - mean) / sd
Rozwijanie funkcji, oczywista składnia.
def zscore(mean: R, sd: R) =
  (x: R) =>
    (x - mean) / sd
Rozwijanie funkcji, oczywista składnia
def zscore(mean: R, sd: R)(x: R) =
  (x - mean) / sd
Rozwijanie funkcji, lukier składniowy, ale wtedy:
val normer =
  zscore(7, 0.4) _
Potrzeba podążającego podkreślenia, aby wydobyć funkcję częściowo zaaplikowaną, tylko przy wersji z lukrem składniowym.
def mapmake[T](g: T => T)(seq: List[T]) =
  seq.map(g)
Typ generyczny.
5.+(3); 5 + 3

(1 to 5) map (_ * 2)
Lukier składniowy dla operatorów infiksowych.
def sum(args: Int*) =
  args.reduceLeft(_+_)
Zmienna liczba argumentów.
pakiety
import scala.collection._
Import wszystkiego z pakietu.
import scala.collection.Vector

import scala.collection.{Vector, Sequence}
Import selektywny.
import scala.collection.{Vector => Vec28}
Import ze zmianą nazwy.
import java.util.{Date => _, _}
Importowanie wszystkiego z java.util poza Date.
Na początku pliku:
package pkg

Definiowanie pakietu według zakresu:
package pkg {
  ...
}

Singleton dla pakietu:
package object pkg {
  ...
}
Deklaracja pakietu.
struktury danych
(1, 2, 3)
Literał krotki (Tuple3).
var (x, y, z) = (1, 2, 3)
Przypisanie z podziałem: rozpakowywanie krotki przy pomocy dopasowywania wzorca.
Źle
var x, y, z = (1, 2, 3)
Ukryty błąd: do każdego przypisana cała krotka.
var xs = List(1, 2, 3)
Lista (niezmienna).
xs(2)
Indeksowanie za pomocą nawiasów (slajdy).
1 :: List(2, 3)
Operator dołożenia elementu na początek listy.
1 to 5
to samo co:
1 until 6

1 to 10 by 2
Składnia dla przedziałów.
()
Jedyny obiekt typu Unit.
Identyczny do void w C i Java.
konstrukcje kontrolne
if (check) happy else sad
Warunek.
if (check) happy

to samo co:
if (check) happy else ()
Lukier składniowy dla warunku.
while (x < 5) {
  println(x)
  x += 1
}
Pętla while.
do {
  println(x)
  x += 1
} while (x < 5)
Pętla do-while.
import scala.util.control.Breaks._

breakable {
  for (x <- xs) {
    if (Math.random < 0.1)
      break
  }
}
Instrukcja przerwania pętli (slajdy).
for (x <- xs if x % 2 == 0)
  yield x * 10

to samo co:
xs.filter(_ % 2 == 0).map(_ * 10)
Intrukcja for: filtrowanie/mapowanie.
for ((x, y) <- xs zip ys)
  yield x * y

to samo co:
(xs zip ys) map {
  case (x, y) => x * y
}
Instrukcja for: przypisanie z podziałem.
for (x <- xs; y <- ys)
  yield x * y

to samo co:
xs flatMap { x =>
  ys map { y =>
    x * y
  }
}
Instrukcja for: iloczyn kartezjański.
for (x <- xs; y <- ys) {
  val div = x / y.toFloat
  println("%d/%d = %.1f".format(x, y, div))
}
Instrukcja for: imperatywnie.
sprintf style.
for (i <- 1 to 5) {
  println(i)
}
Instrukcja for: iterowanie aż do górnej granicy włącznie.
for (i <- 1 until 5) {
  println(i)
}
Instrukcja for: iterowanie poniżej górnej granicy.
pattern matching (dopasowywanie wzorca)
Dobrze
(xs zip ys) map {
  case (x, y) => x * y
}

Źle
(xs zip ys) map {
  (x, y) => x * y
}
Używaj słowa kluczowego case w funkcjach w celu dopasowywania wzorca.
Źle
val v42 = 42
3 match {
  case v42 => println("42")
  case _   => println("Not 42")
}
v42 jest interpretowane jako nazwa pasująca do każdej wartości typu Int, więc "42" zostaje wypisywane.
Dobrze
val v42 = 42
3 match {
  case `v42` => println("42")
  case _     => println("Not 42")
}
`v42` z grawisami jest interpretowane jako istniejąca wartośćv42, więc “Not 42” zostaje wypisywane.
Dobrze
val UppercaseVal = 42
3 match {
  case UppercaseVal => println("42")
  case _            => println("Not 42")
}
UppercaseVal jest traktowane jako istniejąca wartość, nie jako zmienna wzorca, bo zaczyna się z wielkiej litery. W takim razie wartość przechowywana w UppercaseVal jest porównywana z 3, więc “Not 42” jest wypisywane.
obiektowość
class C(x: R)
Parametry konstruktora x - prywatne.
class C(val x: R)

var c = new C(4)

c.x
Parametry konstruktora - publiczne.
class C(var x: R) {
  assert(x > 0, "positive please")
  var y = x
  val readonly = 5
  private var secret = 1
  def this = this(42)
}
Konstruktor jest ciałem klasy.
Deklaracja publicznego pola.
Deklaracja publicznej stałej.
Deklaracja pola prywatnego.
Alternatywny konstruktor.
new {
  ...
}
Instancja klasy anonimowej.
abstract class D { ... }
Defiicja klasy abstrakcyjnej (nie da się stworzyć obiektu tej klasy).
class C extends D { ... }
Definicja klasy pochodnej.
class D(var x: R)

class C(x: R) extends D(x)
Dziedziczenie i parametry konstruktora (wishlist: domyślne, automatyczne przekazywanie parametrów).
object O extends D { ... }
Definicja singletona (w stylu modułu).
trait T { ... }

class C extends T { ... }

class C extends D with T { ... }
Cechy.
Interface'y z implementacją. Bez parametrów konstruktora. Możliwość mixin'ów.
trait T1; trait T2

class C extends T1 with T2

class C extends D with T1 with T2
Wiele cech.
class C extends D { override def f = ...}
W przeciążeniach funkcji wymagane jest słowo kluczowe override.
new java.io.File("f")
Tworzenie obiektu.
Źle
new List[Int]

Dobrze
List(1, 2, 3)
Błąd typu: typ abstrakcyjny.
Zamiast tego konwencja: wywoływalna fabryka przysłaniająca typ.
classOf[String]
Literał klasy.
x.isInstanceOf[String]
Sprawdzanie typu (w czasie wykonania).
x.asInstanceOf[String]
Rzutowanie typu (w czasie wykonania).
x: String
Oznaczenie typu (w czasie kompilacji).
opcje
Some(42)
Tworzenie niepustej wartości opcjonalnej.
None
Pojedyncza pusta wartość opcjonalna.
Option(null) == None
Option(obj.unsafeMethod)
ale
Some(null) != None
Fabryka wartości opcjonalnych null-safe.
val optStr: Option[String] = None
to samo co:
val optStr = Option.empty[String]
Jawny typ pustej wartości opcjonalnej
Fabryka dla pustej wartości opcjonalnej.
val name: Option[String] =
  request.getParameter("name")
val upper = name.map {
  _.trim
} filter {
  _.length != 0
} map {
  _.toUpperCase
}
println(upper.getOrElse(""))
Styl potokowy (pipeline).
val upper = for {
  name <- request.getParameter("name")
  trimmed <- Some(name.trim)
    if trimmed.length != 0
  upper <- Some(trimmed.toUpperCase)
} yield upper
println(upper.getOrElse(""))
Składnia instrukcji for.
option.map(f(_))
to samo co:
option match {
  case Some(x) => Some(f(x))
  case None    => None
}
Zastosuj funkcję do wartości opcjonalnej.
option.flatMap(f(_))
to samo co:
option match {
  case Some(x) => f(x)
  case None    => None
}
To samo co map, ale funkcja musi zwracać opcjonalną wartość.
optionOfOption.flatten
to samo co:
optionOfOption match {
  case Some(Some(x)) => Some(x)
  case _             => None
}
Wyodrębnij opcję zagnieżdżoną.
option.foreach(f(_))
to samo co:
option match {
  case Some(x) => f(x)
  case None    => ()
}
Zastosuj procedurę na wartości opcjonalnej.
option.fold(y)(f(_))
to samo co:
option match {
  case Some(x) => f(x)
  case None    => y
}
Zastosuj funkcję do wartości opcjonalnej, zwróć wartość domyślną, jeśli pusta.
option.collect {
  case x => ...
}
to samo co:
option match {
  case Some(x) if f.isDefinedAt(x) => ...
  case Some(_)                     => None
  case None                        => None
}
Zastosuj częściowe dopasowanie do wzorca dla wartości opcjonalnej.
option.isDefined
to samo co:
option match {
  case Some(_) => true
  case None    => false
}
true jeżeli nie jest puste.
option.isEmpty
to samo co:
option match {
  case Some(_) => false
  case None    => true
}
true jeżeli puste.
option.nonEmpty
to samo co:
option match {
  case Some(_) => true
  case None    => false
}
true jeżeli nie jest puste.
option.size
to samo co:
option match {
  case Some(_) => 1
  case None    => 0
}
0 jeżeli puste, w przeciwnym razie 1.
option.orElse(Some(y))
to samo co:
option match {
  case Some(x) => Some(x)
  case None    => Some(y)
}
Oblicz i zwróć alternatywną wartość opcjonalną, jeżeli pierwotna wartość jest pusta.
option.getOrElse(y)
to samo co:
option match {
  case Some(x) => x
  case None    => y
}
Oblicz i zwróć wartość domyślną, jeżeli pierwotna wartość jest pusta.
option.get
to samo co:
option match {
  case Some(x) => x
  case None    => throw new Exception
}
Zwróć wartość, jeżeli pusta to rzuć wyjątek.
option.orNull
to samo co:
option match {
  case Some(x) => x
  case None    => null
}
Zwróć wartość, null jeżeli pusta.
option.filter(f)
to samo co:
option match {
  case Some(x) if f(x) => Some(x)
  case _               => None
}
Wartość opcjonalna spełnia predyktat.
option.filterNot(f(_))
to samo co:
option match {
  case Some(x) if !f(x) => Some(x)
  case _                => None
}
Wartość opcjonalna nie spełnia predyktatu.
option.exists(f(_))
to samo co:
option match {
  case Some(x) if f(x) => true
  case Some(_)         => false
  case None            => false
}
Zastosuj predyktat na wartości lub false jeżeli pusta.
option.forall(f(_))
to samo co:
option match {
  case Some(x) if f(x) => true
  case Some(_)         => false
  case None            => true
}
Zastosuj predyktat na opcjonalnej wartości lub true jeżeli pusta.
option.contains(y)
to samo co:
option match {
  case Some(x) => x == y
  case None    => false
}
Sprawdź, czy wartość jest równa wartości opcjonalnej lub false jeżeli pusta.
bafrjaplpt-brzh-cnthruuk

Contributors to this page: