Scala #4

20
Patterns

Transcript of Scala #4

Page 1: Scala #4

Patterns

Page 2: Scala #4

Special unapplyclass 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)}

Page 3: Scala #4

Case classes moreТеперь понятнее, что же на самом деле дает case class:case class Person(name: String)val ivan = Person("ivan")ivan.nameivan match { case Person(name) =>}

Page 4: Scala #4

Multiline stringsМногострочные литералы:val s = """ |Some text. |<- This is margin. |It will be stripped below. """.stripMargin

Page 5: Scala #4

Interpolated stringsМожно использовать разные интерполяторы. Дефолтные - это s и f:val name = "Alexander"val city = "Saint-Petersburg"s"My name is $name. I live in $city."val height = 1.8311df"$name%s’s height is $height%2.2f"

Page 6: Scala #4

Regular expressionsval 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)}

Page 7: Scala #4

unapplySeqobject ListLike { def unapplySeq[T](l: List[T]): Option[Seq[T]] = Some(l)}List(1, 2, 3) match{ case ListLike(1, xs@_*) => println(xs) case _ =>}

Page 8: Scala #4

Other patternsobject ** { 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 =>}

Page 9: Scala #4

Pattern guardsМожно накладывать условия на case clause:val x, y: Int = 1(x, y) match { case (a, b) if a == b => case _ =>}

Page 10: Scala #4

ScopesScopes - это место в коде, где может быть объявлена переменная. ● { - начинает новый scope, кроме классов ● Каждый генератор в for statement начинает

новый scope ● Функция начинает новый scope для

параметров ● Case clause начинает новый scope Переменная объявленная внутри одного scope не видна снаружи.

Page 11: Scala #4

Names shadowingВо внутреннем scope можно скрывать имя определенное во внешнем scope при условии, что приоритет этого имени не ниже чем у имени объявленного снаружи.

Это ошибка объявить переменные с одним именем внутри одного и того же scope.

Существует два вида имен: expressions, types.

Page 12: Scala #4

Implicits

Page 13: Scala #4

Implicit conversionsПреследует две главные цели:● Extension methods● DSL languages

Позволяет неявно в коде конвертировать один тип в другой.

Page 14: Scala #4

Implicit conversionsПростейшие примеры:class RichString(s: String) { def double: String = s + s}implicit def s2r(s: String): RichString = new RichString(s)

"text".doubleval r: RichString = "text""""^[^\d].*""".r

Page 15: Scala #4

Implicit classesВ Scala 2.10 есть более простой вариант:implicit class RichString(s: String) { def double: String = s + s}

"text".double

Page 16: Scala #4

Value classesPerformance overhead на удаление в GC новых объектов существенный. Поэтому для extension methods можно сделать так:

implicit class RichString(val s: String) extends AnyVal { def double: String = s + s}"text".double

Page 17: Scala #4

Implicits search1. Сначала ищем в scope2. Если не нашли, то расширяем scope с

помощью companion objects частей типа, для которого ищем конверсию

Page 18: Scala #4

How to debug implicits?Неявно это хорошо, когда все работает.Что делать, если не работает:● -Xprint:typer параметр для компилятора● IntelliJ IDEA view implicits tools

Page 19: Scala #4

Magnet patternПример использования implicits:● Нет проблемы с type erasure для

перегруженных методов● Автоматически выносится общая часть

для перегруженных методов● Использование функциональных типов с

перегрузкой

Page 20: Scala #4

HomeworkНаписать интерпретируемый язык программирования. Синтаксис и все остальное дело вашего вкуса. Базовая спецификация следующая:1. Динамически типизируемый. У целых и вещественных чисел нет переполнения.2. Можно объявлять целые, вещественные и стоковые литералы.3. Можно объявлять переменные и функции. В функциях можно задавать значения по умолчанию.4. Можно эти переменные и функции вызывать.5. Можно создавать структуры без наследования. Просто данные, и возможно какие-то методы.