Last active
August 29, 2015 14:22
-
-
Save groz/ad8f962de5e35923339a to your computer and use it in GitHub Desktop.
Scala cheat sheet (ru)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
В одном проекте и даже одном файле может быть объявлено несколько приложений (или точек входа). | |
Запуск нужного производится следующей командой: | |
$ sbt "run-main <полное имя объекта>" | |
Пример: | |
$ sbt "run-main Integers" | |
*/ | |
// --------------------------------------------------------------- | |
// Целые числа и простые операции | |
// --------------------------------------------------------------- | |
object Integers extends App { | |
// Объявление переменной типа Int. | |
val sampleInteger: Int = 176 | |
// Совершить некоторые вычисления используя предыдущее объявление. | |
// Тип выводится из правой части. | |
val sampleInteger2 = (sampleInteger / 4 + 5 - 7) * 4 | |
// Список целых чисел от 0 до 99 | |
val sampleNumbers = 0 to 99 | |
// Список всех пар чисел от 0 до 99 и их квадратов | |
val sampleTableOfSquares = for (i <- 0 to 99) yield (i, i * i) | |
// Следующая строка выводит список кортежей используя строковую интерполяцию (префикс s перед ") | |
println(s"The table of squares from 0 to 99 is:\n $sampleTableOfSquares") | |
} | |
object BasicFunctions extends App { | |
// Используем 'def' чтобы объявить функцию, которая принимает целое и возвращает целое. | |
// Тип возвращаемого значения выведен из правой части. | |
def func1(x: Int): Int = x * x + 3 | |
// Применим функцию, присвоив результат константе объявленной через 'val'. | |
// Тип переменной выведен из типа возвращаемого значение функции. | |
val result1 = func1(4573) | |
println(s"The result of squaring the integer 4573 and adding 3 is $result1") | |
// Условное выражение if/else возвращает значение. | |
def func2(x: Double) = | |
if (x < 100.0) | |
2.0 * x * x - x / 5.0 + 3.0 | |
else | |
2.0 * x * x + x / 5.0 - 37.0 | |
val result2 = func2(6.5 + 4.5) | |
println(s"The result of applying the 2nd sample function to (6.5 + 4.5) is $result2") | |
} | |
// --------------------------------------------------------------- | |
// Булевы выражения | |
// --------------------------------------------------------------- | |
object SomeBooleanValues extends App { | |
val boolean1 = true | |
val boolean2 = false | |
val boolean3 = !boolean1 && (boolean2 || false) | |
println(s"The expression '!boolean1 && (boolean2 || false)' is $boolean3") | |
} | |
// --------------------------------------------------------------- | |
// Кортежи (упорядоченные множества значений) | |
// --------------------------------------------------------------- | |
object Tuples extends App { | |
/// Простой кортеж целых чисел | |
val tuple1 = (1, 2, 3) | |
// Функция, которая меняет местами два значения в кортеже | |
def swapElems[T](a: T, b: T) = (b, a) | |
println(s"The result of swapping (1, 2) is ${swapElems (1,2)}") | |
// Кортеж из целого числа, строки и числа с плавающей запятой | |
val tuple2 = (1, "fred", 3.1415) | |
println(s"tuple1: $tuple1 tuple2: $tuple2") | |
} | |
// --------------------------------------------------------------- | |
// Списки и операции над списками | |
// --------------------------------------------------------------- | |
object Lists extends App { | |
val list1 = Nil // пустой список | |
// список из трех элементов | |
val list2 = List(1, 2, 3) | |
val list3 = 42 :: list2 // новый список с числом 42 добавленным в начало | |
val numberList: List[Int] = (1 to 1000).toList // список всех целых чисел от 1 до 1000 | |
// Последовательность содержащая все пары координат черных клеток на шахматной доске | |
def blackSquares = | |
for { | |
i <- 0 to 7 | |
j <- 0 to 7 | |
if (i + j) % 2 == 1 | |
} yield (i, j) | |
// Возвести в квадрат все числа в numberList используя метод List.map | |
val squares = numberList.map(x => x * x) | |
// Вычислить суммы квадратов чисел делящихся на 3. | |
val sumOfSquares: Int = | |
numberList | |
.filter(_ % 3 == 0) // упрощенная версия .filter(x => x % 3 == 0) | |
.map(x => x * x) | |
.sum | |
println(s"Sum: $sumOfSquares") | |
} | |
// --------------------------------------------------------------- | |
// Recursive functions | |
// --------------------------------------------------------------- | |
object RecursiveFunctions extends App { | |
// Вычисляет факториал целого числа | |
def factorial(n: Int): Int = | |
if (n == 0) 1 else n * factorial (n-1) | |
// Вычисляет НОД двух целых чисел | |
// Т.к. все рекурсивные вызовы являются хвостовыми, компилятор развернет функцию в цикл, | |
// что улучшит производительность и уменьшит потребление памяти. | |
def greatestCommonFactor(a: Int, b: Int): Int = | |
if (a == 0) b | |
else if (a < b) greatestCommonFactor(a, b - a) | |
else greatestCommonFactor(a - b, b) | |
// Вычисляет сумму элементов списка целых чисел используя рекурсию | |
def sumList(xs: List[Int]): Int = xs match { | |
case Nil => 0 | |
case y :: ys => y + sumList(ys) | |
} | |
// Переделаем ее в функцию с хвостовой рекурсией используя вложенную вспомогательную функцию с аккумулятором результата | |
def sumListTailRecursive(xs: List[Int]) = { | |
def sumListTailRecHelper(accumulator: Int, xs: List[Int]): Int = xs match { | |
case Nil => accumulator | |
case y :: ys => sumListTailRecHelper(accumulator+y, ys) | |
} | |
sumListTailRecHelper(0, xs) // вызовем вспомогательную функцию | |
} | |
} | |
// --------------------------------------------------------------- | |
// Классы | |
// --------------------------------------------------------------- | |
// object создает объект-синглтон | |
object DefiningClasses extends App { | |
// Конструктор класса принимает два аргумента: dx и dy, оба типа 'double'. | |
class Vector2D(dx: Double, dy: Double) { | |
// Длина вектора, вычисленная при создании объекта | |
val length = Math.sqrt(dx * dx + dy * dy) | |
def scale(k: Double) = new Vector2D(k * dx, k * dy) | |
// Scala позволяет давать функциям практически любые название, поэтому | |
// любой оператор это просто функция | |
def *(k: Double) = scale(k) | |
// Функция со специальным названием apply применяется при вызове () на объекте класса. | |
def apply(i: Int) = if (i == 0) dx else dy | |
} | |
// Переменная типа Vector2D | |
val vector1 = new Vector2D(3.0, 4.0) | |
// Получаем новый масштабированный объект типа Vector2D не меняя исходный объект | |
val vector2 = vector1.scale(10.0) | |
// Если у функции один аргумент, то можно опустить .() | |
val vector3 = vector2 scale 5.0 | |
val vector4 = vector3 * 2.0 | |
// Получим координату dx вызовом метода apply на объекте vector2 | |
val x = vector2(0) // "синтаксический сахар" для vector2.apply(0) | |
// Все переменные объявленные внутри класса по умолчанию имеют модификатор public. | |
val (l1, l2) = (vector1.length, vector2.length) | |
println(s"Length of vector1: $l1, Length of vector2: $l2, x: $x") | |
} | |
// --------------------------------------------------------------- | |
// Pattern matching | |
// --------------------------------------------------------------- | |
object PatternMatching extends App { | |
// Case-класс хранящий имя и фамилию человека | |
case class Person(first: String, last: String) | |
// объявим абстрактный класс работников и три конкретных подкласса | |
abstract class Employee | |
case class Engineer(id: Person) extends Employee | |
case class Manager(id: Person, reports: List[Employee]) extends Employee | |
case class Executive(id: Person, reports: List[Employee], assistant: Employee) extends Employee | |
// считает всех подчиненных данного работника, включая его самого | |
def countReports(emp: Employee): Int = 1 + (emp match { | |
case Engineer(_) => 0 | |
case Manager(_, reports) => reports.map(countReports).sum | |
case Executive(_, reports, a) => reports.map(countReports).sum + countReports(a) | |
}) | |
// найти всех менеджеров или управленцев по имени "Dave" у которых нет подчиненных | |
// find all managers/executives named "Dave" who do not have any reports | |
def findDaveWithOpenPosition(emps: List[Employee]) = | |
emps.filter { | |
case Manager(Person("Dave", _), Nil) => true | |
case Executive(Person("Dave", _), Nil, _) => true | |
} | |
// специальный символ _ в данном контексте означает "любое значение" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment