Patterns
Special unapply 
class A { 
def _1: Int = 1 
def _2: String = "text" 
} 
class B { 
def isEmpty = false 
def get = new A 
} 
object K { 
def unapply(s: String): B = 
new B 
} 
"text" match { 
case K(i, s) => 
println(i, s) 
}
Case classes more 
Теперь понятнее, что же на самом деле 
дает case class: 
case class Person(name: String) 
val ivan = Person("ivan") 
ivan.name 
ivan match { 
case Person(name) => 
}
Multiline strings 
Многострочные литералы: 
val s = 
""" 
|Some text. 
|<- This is margin. 
|It will be stripped below. 
""".stripMargin
Interpolated strings 
Можно использовать разные 
интерполяторы. Дефолтные - это s и f: 
val name = "Alexander" 
val city = "Saint-Petersburg" 
s"My name is $name. I live in $city." 
val height = 1.8311d 
f"$name%s’s height is $height%2.2f"
Regular expressions 
val Decimal = """(-)?(d+)(.d*)?""".r 
"1.0" match { 
case Decimal(sign, i, d) => 
case _ => 
} 
val Decimal(sign, i, d) = "1.0" 
val iterator = Decimal findAllIn "1.0 and 2.0, 33" 
for (Decimal(sign, i, d) <- iterator) { 
println(i) 
}
unapplySeq 
object ListLike { 
def unapplySeq[T](l: List[T]): Option[Seq[T]] = 
Some(l) 
} 
List(1, 2, 3) match{ 
case ListLike(1, xs@_*) => 
println(xs) 
case _ => 
}
Other patterns 
object ** { 
def unapply(t: (Int, Int)): Some[(Int, Int)] = Some(t) 
} 
val x, y: Int = 1 
(x, y) match { 
case (1, 2) | (2, 1) => 
case 1 ** 1 => 
}
Pattern guards 
Можно накладывать условия на case clause: 
val x, y: Int = 1 
(x, y) match { 
case (a, b) if a == b => 
case _ => 
}
Scopes 
Scopes - это место в коде, где может быть 
объявлена переменная. 
● { - начинает новый scope, кроме классов 
● Каждый генератор в for statement начинает 
новый scope 
● Функция начинает новый scope для 
параметров 
● Case clause начинает новый scope 
Переменная объявленная внутри одного scope 
не видна снаружи.
Names shadowing 
Во внутреннем scope можно скрывать имя 
определенное во внешнем scope при условии, 
что приоритет этого имени не ниже чем у имени 
объявленного снаружи. 
Это ошибка объявить переменные с одним 
именем внутри одного и того же scope. 
Существует два вида имен: expressions, types.
Implicits
Implicit conversions 
Преследует две главные цели: 
● Extension methods 
● DSL languages 
Позволяет неявно в коде конвертировать 
один тип в другой.
Implicit conversions 
Простейшие примеры: 
class RichString(s: String) { 
def double: String = s + s 
} 
implicit def s2r(s: String): RichString = new RichString(s) 
"text".double 
val r: RichString = "text" 
"""^[^d].*""".r
Implicit classes 
В Scala 2.10 есть более простой вариант: 
implicit class RichString(s: String) { 
def double: String = s + s 
} 
"text".double
Value classes 
Performance overhead на удаление в GC 
новых объектов существенный. Поэтому для 
extension methods можно сделать так: 
implicit class RichString(val s: String) 
extends AnyVal { 
def double: String = s + s 
} 
"text".double
Implicits search 
1. Сначала ищем в scope 
2. Если не нашли, то расширяем scope с 
помощью companion objects частей типа, 
для которого ищем конверсию
How to debug implicits? 
Неявно это хорошо, когда все работает. 
Что делать, если не работает: 
● -Xprint:typer параметр для компилятора 
● IntelliJ IDEA view implicits tools
Magnet pattern 
Пример использования implicits: 
● Нет проблемы с type erasure для 
перегруженных методов 
● Автоматически выносится общая часть 
для перегруженных методов 
● Использование функциональных типов с 
перегрузкой
Homework 
Написать интерпретируемый язык программирования. Синтаксис и 
все остальное дело вашего вкуса. Базовая спецификация 
следующая: 
1. Динамически типизируемый. У целых и вещественных чисел нет 
переполнения. 
2. Можно объявлять целые, вещественные и стоковые литералы. 
3. Можно объявлять переменные и функции. В функциях можно 
задавать значения по умолчанию. 
4. Можно эти переменные и функции вызывать. 
5. Можно создавать структуры без наследования. Просто данные, 
и возможно какие-то методы.

Scala #4

  • 1.
  • 2.
    Special unapply classA { def _1: Int = 1 def _2: String = "text" } class B { def isEmpty = false def get = new A } object K { def unapply(s: String): B = new B } "text" match { case K(i, s) => println(i, s) }
  • 3.
    Case classes more Теперь понятнее, что же на самом деле дает case class: case class Person(name: String) val ivan = Person("ivan") ivan.name ivan match { case Person(name) => }
  • 4.
    Multiline strings Многострочныелитералы: val s = """ |Some text. |<- This is margin. |It will be stripped below. """.stripMargin
  • 5.
    Interpolated strings Можноиспользовать разные интерполяторы. Дефолтные - это s и f: val name = "Alexander" val city = "Saint-Petersburg" s"My name is $name. I live in $city." val height = 1.8311d f"$name%s’s height is $height%2.2f"
  • 6.
    Regular expressions valDecimal = """(-)?(d+)(.d*)?""".r "1.0" match { case Decimal(sign, i, d) => case _ => } val Decimal(sign, i, d) = "1.0" val iterator = Decimal findAllIn "1.0 and 2.0, 33" for (Decimal(sign, i, d) <- iterator) { println(i) }
  • 7.
    unapplySeq object ListLike{ def unapplySeq[T](l: List[T]): Option[Seq[T]] = Some(l) } List(1, 2, 3) match{ case ListLike(1, xs@_*) => println(xs) case _ => }
  • 8.
    Other patterns object** { def unapply(t: (Int, Int)): Some[(Int, Int)] = Some(t) } val x, y: Int = 1 (x, y) match { case (1, 2) | (2, 1) => case 1 ** 1 => }
  • 9.
    Pattern guards Можнонакладывать условия на case clause: val x, y: Int = 1 (x, y) match { case (a, b) if a == b => case _ => }
  • 10.
    Scopes Scopes -это место в коде, где может быть объявлена переменная. ● { - начинает новый scope, кроме классов ● Каждый генератор в for statement начинает новый scope ● Функция начинает новый scope для параметров ● Case clause начинает новый scope Переменная объявленная внутри одного scope не видна снаружи.
  • 11.
    Names shadowing Вовнутреннем scope можно скрывать имя определенное во внешнем scope при условии, что приоритет этого имени не ниже чем у имени объявленного снаружи. Это ошибка объявить переменные с одним именем внутри одного и того же scope. Существует два вида имен: expressions, types.
  • 12.
  • 13.
    Implicit conversions Преследуетдве главные цели: ● Extension methods ● DSL languages Позволяет неявно в коде конвертировать один тип в другой.
  • 14.
    Implicit conversions Простейшиепримеры: class RichString(s: String) { def double: String = s + s } implicit def s2r(s: String): RichString = new RichString(s) "text".double val r: RichString = "text" """^[^d].*""".r
  • 15.
    Implicit classes ВScala 2.10 есть более простой вариант: implicit class RichString(s: String) { def double: String = s + s } "text".double
  • 16.
    Value classes Performanceoverhead на удаление в GC новых объектов существенный. Поэтому для extension methods можно сделать так: implicit class RichString(val s: String) extends AnyVal { def double: String = s + s } "text".double
  • 17.
    Implicits search 1.Сначала ищем в scope 2. Если не нашли, то расширяем scope с помощью companion objects частей типа, для которого ищем конверсию
  • 18.
    How to debugimplicits? Неявно это хорошо, когда все работает. Что делать, если не работает: ● -Xprint:typer параметр для компилятора ● IntelliJ IDEA view implicits tools
  • 19.
    Magnet pattern Примериспользования implicits: ● Нет проблемы с type erasure для перегруженных методов ● Автоматически выносится общая часть для перегруженных методов ● Использование функциональных типов с перегрузкой
  • 20.
    Homework Написать интерпретируемыйязык программирования. Синтаксис и все остальное дело вашего вкуса. Базовая спецификация следующая: 1. Динамически типизируемый. У целых и вещественных чисел нет переполнения. 2. Можно объявлять целые, вещественные и стоковые литералы. 3. Можно объявлять переменные и функции. В функциях можно задавать значения по умолчанию. 4. Можно эти переменные и функции вызывать. 5. Можно создавать структуры без наследования. Просто данные, и возможно какие-то методы.