Skip to content

Instantly share code, notes, and snippets.

@groz
Last active August 29, 2015 14:22
Show Gist options
  • Save groz/ad8f962de5e35923339a to your computer and use it in GitHub Desktop.
Save groz/ad8f962de5e35923339a to your computer and use it in GitHub Desktop.
Scala cheat sheet (ru)
/*
В одном проекте и даже одном файле может быть объявлено несколько приложений (или точек входа).
Запуск нужного производится следующей командой:
$ 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