Scala Cheatsheet

Scalacheat

Language
Contributed by Filip Czaplicki

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 zmienna
Dobrze 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 }
definicja funkcji
ukryty błąd: bez znaku = jest to procedura zwracająca Unit; powoduje to chaos
Dobrze def f(x: Any) = println(x)
Źle def f(x) = println(x)
definicja funkcji
błąd składni: potrzebne są typy dla każdego argumentu.
type R = Double alias typu
def f(x: R) vs.
def f(x: => R)
wywołanie przez wartość
wywołanie przez nazwę (parametry leniwe)
(x:R) => x*x funkcja anonimowa
(1 to 5).map(_*2) vs.
(1 to 5).reduceLeft( _+_ )
funkcja anonimowa: podkreślenie to argument pozycjonalny
(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. (lub ponawiasowane).
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 wiodącego podkreślenia, aby wydobyć funkcję częściowo zaaplikowaną, tylko dla 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 funkcji.
pakiety  
import scala.collection._ import wszystkiego z danego 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.
package pkg na początku pliku
package 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.
Źlevar 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.
() (puste nawiasy) jedyny obiekt typu Unit (podobnie jak void w C/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 (break). (slides)
for (x <- xs if x%2 == 0) yield x*10 to samo co
xs.filter(_%2 == 0).map(_*10)
instrukcja 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) {
println("%d/%d = %.1f".format(x, y, x/y.toFloat))
}
instrukcja for: imperatywnie
sprintf-style
for (i <- 1 to 5) {
println(i)
}
instrukcja for: iterowanie aż do górnej granicy
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 (pattern matching).
Źle
val v42 = 42
Some(3) match {
case Some(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
Some(3) match {
case Some(`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
Some(3) match {
case Some(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” zostaje wypisywane.
obiektowość  
class C(x: R) to samo co
class C(private val x: R)
var c = new C(4)
parametry konstruktora - 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{ ... } klasa anonimowa
abstract class D { ... } definicja 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] sprawdzenie typu (w czasie wykonania)
x.asInstanceOf[String] rzutowanie typu (w czasie wykonania)
x: String oznaczenie typu (w czasie kompilacji)
bafrjaplpt-brzh-cnth

Contributors to this page: