Scala Cheatsheet

Scala Cheatsheet

Language
Contributed by Dima Kotobotov

Эта шпаргалка создана благодаря Brendan O’Connor и предназначена для быстрого ознакомления с синтаксическими конструкциями Scala. Лицензия выдана Brendan O’Connor по лицензии CC-BY-SA 3.0.

переменные
var x = 5 переменная
Хорошо
val x = 5
Плохо
x=6
константа
var x: Double = 5 явное указание типа
функции
Хорошо
def f(x: Int) = { x*x }
Плохо
def f(x: Int) { x*x }
объявление функции
незаметная ошибка: без = это процедура с возвращаемым типом "Unit". Такое может ввести в заблуждение
Хорошо
def f(x: Any) = println(x)
Плохо
def f(x) = println(x)
объявление функции
синтаксическая ошибка: для каждого аргумента необходимо указывать его тип.
type R = Double псевдоним для типа
def f(x: R) vs.

def f(x: => R)
вызов по значению
вызов по имени (вычисление аргумента отложено)
(x:R) => x*x анонимная функция
(1 to 5).map(_*2) vs.
(1 to 5).reduceLeft( _+_ )
анонимная функция: подчеркивание указывает место подставляемого элемента.
(1 to 5).map( x => x*x ) анонимная функция: слева от => задается имя подставляемого элемента, чтоб его можно было переиспользовать
Хорошо
(1 to 5).map(2*)
Плохо
(1 to 5).map(*2)
анонимная функция: запись с использованием инфиксного стиля. Ради четкого понимания лучше использовать явное указание позиции подставляемого элемента в стиле 2*_.
(1 to 5).map { x => val y=x*2; println(y); y } анонимная функция: стиль блоковой передачи (фигурные скобки обозначают блок), возвращается последнее значение (y).
(1 to 5) filter {_%2 == 0} map {_*2} анонимные функции: конвейерный стиль. В однострочных выражениях можно использовать простые скобки.
def compose(g:R=>R, h:R=>R) = (x:R) => g(h(x))
val f = compose({_*2}, {_-1})
анонимные функции: передача блоков в качестве аргументов
val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd каррирование, явный синтаксис.
def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd каррирование, явный синтаксис
def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd каррирование, синтаксический сахар. Но если :
val normer = zscore(7, 0.4) _ следом использовать подчеркивание, то мы получим частично определенную функцию.
def mapmake[T](g:T=>T)(seq: List[T]) = seq.map(g) обобщенный тип.
5.+(3); 5 + 3
(1 to 5) map (_*2)
инфиксный стиль.
def sum(args: Int*) = args.reduceLeft(_+_) функция с переменным числом аргументов.
пакеты
import scala.collection._ импорт всех членов пакета.
import scala.collection.Vector
import scala.collection.{Vector, Sequence}
выборочный импорт.
import scala.collection.{Vector => Vec28} импорт с переименованием.
import java.util.{Date => _, _} импортировать все из java.util кроме Date.
package pkg в самом начале файла
package pkg { ... }
объявление пакета.
структуры данных
(1,2,3) кортеж размера 3. (Tuple3)
var (x,y,z) = (1,2,3) разложение на отдельные элементы: кортеж раскладывается на элементы x, y и z используя сопоставление с образцом.
Плохо
var x,y,z = (1,2,3)
незаметная ошибка: каждой переменной будет присвоено по кортежу.
var xs = List(1,2,3) список (неизменяемый).
xs(2) получение элемента по индексу в скобках. (примеры)
1 :: List(2,3) добавление к списку.
1 to 5 тоже что и 1 until 6
1 to 10 by 2
задание диапазона (синтаксический сахар).
() (пустые скобки) одиночный член типа Unit (тоже что и void в C/Java).
управляющие структуры
if (check) happy else sad условие.
if (check) happy
тоже что и
if (check) happy else ()
синтаксический сахар (ветка else добавляется автоматически).
while (x < 5) { println(x); x += 1} цикл с условием в блоке while .
do { println(x); x += 1} while (x < 5) цикл с условием и обязательным исполнением в блоке do.
import scala.util.control.Breaks._
breakable {
  for (x <- xs) {
    if (Math.random < 0.1)
      break
  }
}
выход из цикла с использованием break. (примеры)
for (x <- xs if x%2 == 0) yield x*10
тоже что и
xs.filter(_%2 == 0).map(_*10)
for-выражение: выражается набором с filter/map
for ((x,y) <- xs zip ys) yield x*y
тоже что и
(xs zip ys) map { case (x,y) => x*y }
for-выражение: извлечение элементов с последующим вычислением
for (x <- xs; y <- ys) yield x*y
тоже что и
xs flatMap {x => ys map {y => x*y}}
for-выражение: перекрестное объединение
for (x <- xs; y <- ys) {
  println("%d/%d = %.1f".format(x, y, x/y.toFloat))
}
for-выражение: императивно
sprintf-style
for (i <- 1 to 5) {
  println(i)
}
for-выражение: обход диапазона (от 1 до 5) включая его верхнюю границу
for (i <- 1 until 5) {
  println(i)
}
for-выражение: обход диапазона (от 1 до 5) не включая его верхнюю границу
сопоставление с примером
Хорошо
(xs zip ys) map { case (x,y) => x*y }
Плохо
(xs zip ys) map( (x,y) => x*y )
используйте ключевое слово case при передачи аргументов в функцию для запуска механизма сопоставления с примером.
Плохо
val v42 = 42
Some(3) match {
  case Some(v42) => println("42")
  case _ => println("Not 42")
}
“v42” интерпретировано как имя для новой константы любого типа, поэтому напечатано “42”.
Хорошо
val v42 = 42
Some(3) match {
  case Some(`v42`) => println("42")
  case _ => println("Not 42")
}
”`v42`” с обратными кавычками интерпретируется как указание на значение существующей константы v42, напечатано “Not 42”.
Хорошо
val UppercaseVal = 42
Some(3) match {
  case Some(UppercaseVal) => println("42")
  case _ => println("Not 42")
}
UppercaseVal однако константы, имена которых начинаются с заглавной буквы, сопоставляются по значению. Поэтому при сопоставлении UppercaseVal с 3, выводится “Not 42”.
Работа с объектами
class C(x: R) параметр конструктора - x доступен только внутри тела класса
class C(val x: R)
var c = new C(4)
c.x
параметр конструктора - доступен публично, автоматически
class C(var x: R) {
  assert(x > 0, "positive please")
  var y = x
  val readonly = 5
  private var secret = 1
  def this() = this(42)
}
конструктор является телом класса
объявление публичного члена класса
объявление члена с гетером но без сеттера
объявление приватного члена
объявление альтернативного конструктора без аргумента
new{ ... } анонимный класс
abstract class D { ... } объявление абстрактного класса (не создаваемого, только наследуемого)
class C extends D { ... } объявление класса с наследованием.
class D(var x: R)
class C(x: R) extends D(x)
наследование класса с конструированием параметров.
object O extends D { ... } объявление объекта одиночки (Singleton) на основе другого класса.
trait T { ... }
class C extends T { ... }
class C extends D with T { ... }
трейты
описывают какие функции и данные должны быть в классе, возможно также указание конкретной (или общей) реализации а также указание значений переменных. у трейта нет конструктора. их можно смешивать.
trait T1; trait T2
class C extends T1 with T2
class C extends D with T1 with T2
множественные трейты.
class C extends D { override def f = ...} при наследовании и создании методов с одинаковыми именами необходимо указывать override.
new java.io.File("f") создание объекта.
Плохо
new List[Int]
Хорошо
List(1,2,3)
ошибка: List - это абстрактный класс
по соглашению используется объект с именем как у абстрактного класса, который уже создает конкретные экземпляры
classOf[String] описание класса.
x.isInstanceOf[String] проверка типа (при исполнении)
x.asInstanceOf[String] приведение типа (при исполнении)
x: String приписывание типа (во время компиляции)
bafrjaplpt-brzh-cnthruuk

Contributors to this page: