29
Scala #4 Scopes, XML, Scala type system

Scala lecture #4

Embed Size (px)

Citation preview

Page 1: Scala lecture #4

Scala #4Scopes, XML, Scala type system

Page 2: Scala lecture #4

Scopes

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

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

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

Page 3: Scala lecture #4

Names shadowing

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

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

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

Page 4: Scala lecture #4

Think functional

Давайте напишем программу вывода таблицы умножения (см. Programming Scala)

Page 5: Scala lecture #4

Initialization

Инициализация происходит в обратом порядке, нежели линеаризация. Порядок важно понимать, иначе можно заработать NullPointerException:

Page 6: Scala lecture #4

Initializationobject InitializationNPE {

class A {

val x1 = "text"

val x2 = x1.length

}

class B extends A {

override val x1 = "text1"

}

def main(args: Array[String]) {

new B

}

}

Page 7: Scala lecture #4

Initialization

Есть два способа решить эту проблему● Early definitions● Lazy initialization

Page 8: Scala lecture #4

Early definitions

Если нужно определить что-то до вызова super конструктора, это можно сделать в early definitions:

class B(x: Int)

class A(s: String) extends {

val i = s.toInt

} with B(i * i)

Page 9: Scala lecture #4

Initialization (early defs)object InitializationNPE {

class A {

val x1 = "text"

val x2 = x1.length

}

class B extends {

override val x1 = "text1"

} with A

def main(args: Array[String]) {

new B

}

}

Page 10: Scala lecture #4

Lazy values

Scala поддерживает синтиаксис ленивых вычислений. От пользователя требуется лишь объявить переменную, как lazy.

Реализация double-checked locking, что приводит к определенным сложностям.

Page 11: Scala lecture #4

Initialization (lazy vals)object InitializationNPE {

class A {

lazy val x1 = "text"

val x2 = x1.length

}

class B extends A {

override lazy val x1 = "text1"

}

def main(args: Array[String]) {

new B

}

}

Page 12: Scala lecture #4

Few words about traits

Как же компилируются traits, рассмотрим простой пример:

trait Base {

def foo() = 1

}

class Child extends Base

Page 13: Scala lecture #4

Few words about traitspublic interface Base {

int foo();

}

public class Base$class {

public static int foo(Base base) {

return 1;

}

}

public class Child implements Base {

public int foo() {

return Base$class.foo(this);

}

}

Page 14: Scala lecture #4

Embedded XML

Практически любой валидный XML можно использовать как литерал:

val xml1 = <a>Some text<b/></a>val xml2 = <a>{3 + 4}</a>val xml3 = <a>{"</a>It's just String<a>"}</a>

Если надо написать {, то его можно заэскейпить {{.

Page 15: Scala lecture #4

XML API

Базовый класс scala.xml.Node.Доступ к subelement через \ “name”.К аттрибутам через \ “@name”.Рекурсивный поиск в глубину \\ “name”.

val xml = <a id="text"><b>S<c></c></b></a>

xml.text // S

xml \ "b" // <b>S<c></c></b>

xml \ "@id" // text

xml \\ "c" // <c></c>

Page 16: Scala lecture #4

Using XML

Встроенный XML легко использовать для сериализации:

val node = <x></x>

scala.xml.XML.save("File.xml", node)

scala.xml.XML.load("File.xml")

Page 17: Scala lecture #4

Pattern matching

В pattern matching есть особый синтаксис для XML:

val node = <x></x>

scala.xml.XML.save("File.xml", node)

scala.xml.XML.load("File.xml")

Page 18: Scala lecture #4

Scala type system

Page 19: Scala lecture #4

Basic types

● Primitive types● Type designators● Parameterized types● Tuple types● Function types● Infix types● Type projections● Singleton types● Annotated types

Page 20: Scala lecture #4

Advanced types

● Structural types● Existential types● Method types (internal type)● Polymorphic method types (internal type)● Type constructors (internal type)

Page 21: Scala lecture #4

Primitive types

Есть несколько важных фич:● Numeric Widening. Если работает weak

conformance, то он автоматический.● Literal Narrowing. Literal с ожидаемым

типом Byte, Short or Char конвертируется.● Value discarding. Если тип Uеnit, то для

любого выражения, есть конверсия.Value classes также наследуются от AnyVal.

Page 22: Scala lecture #4

Type designators

Это просто любой class, trait или object как тип. Ничего особенного здесь не подразумевается.

Page 23: Scala lecture #4

Parameterized types

Для type designator и его type parameters есть два правила:● Число type parameters должно of underli

совпадать с числом параметорв соответствующего класса type designator.

● Каждый type parameter должен подходить к type parameter bounds

Page 24: Scala lecture #4

Tuple types

Синтаксический сахар для TupleN[T1, ..., Tn] типа. Subtyping разрешается также, как и subtyping соответствующего TupleN класс согласно вариантности.Поэтому этот код и не скомпилируется:

object A {

def foo(x: (Int, Int)) = x._1 + x._2

def foo(x: (String, String)) = x._1 + x._2

}

Page 25: Scala lecture #4

Automatic tupling

Позволяет избежать лишних скобок, особенно это полезно для infix нотации.

object A {

def foo(x: (Int, Int)) = x._1 + x._2

}

A.foo((1, 2))

A.foo(1, 2)

A foo (1, 2)

println(1, 2, 3)

Page 26: Scala lecture #4

Function type

Уже подробно изученный нами синтаксический сахар. В силу недосмотра в компиляторе это несовсем синтаксический сахар:

val x1: Function1[Int, Int] = x => x + 1

val x2: Int => Int = _ + 1

val y1: Function1[Seq[Int], Int] = x => x.length

val y2: (Int*) => Int = x => x.length

Page 27: Scala lecture #4

Annotated types

Любой тип можно проаннотировать. С точки зрения системы типов эта аннотация будет проигнорирована:

class A

val a: A @serializable = new A

Page 28: Scala lecture #4

Infix types

Синтаксический сахар (опять?..)

class :::[T, S]

val x: :::[Int, Int] = new :::

val y: Int ::: Int = new :::

Page 29: Scala lecture #4

Infix types

Может быть полезно для операторов над типами:

type n[A] = A => Nothing

type ++[T, U] = n[n[T] with n[U]]

type nn[A] = n[n[A]]

type |+|[T, U] = { type λ[X] = nn[X] <:< (T ++ U) }

def size[T : (Int |+| String)#λ] (t: T) = t match {

case i: Int => i

case s: String => s.length

}