Обзор scala (гостевая лекция)
TRANSCRIPT
Scala: краткий обзор
перед "собственно изучением" <[email protected]>(см. текст: http://bit.ly/sEfCyr )
Scala
Язык
• язык общего назначения• выражающий распространенные модели программирования
o кратким,o элегантным o и типизированным образом
• Он бесшовно интегрирует в себе o функциональную и объектно-ориентированные парадигмы языков
программирования • позволяя Java разработчикам (как и другим) быть более
продуктивными.
Scala ~ Java
• Компилируется в JVMo (версии для CLR LLVM - экспериметнальны)
• Реиспользует инфраструктуру и библиотекиo jetty, tomcato akka (scala => java)
• Находится в одном контекстеo Мартин Одесски -- автор Generic в JDK-1.5
Типизация
• Статическая
Map<String,String> map = new TreeMap<String,String>();int x = 5;
• Динамическая
def map = new TreeMap<String,String>(). def x = 5;
• Вывод типов (статическая но без многословности)
val map = TreeMap[String,String]() val x = 5
Scala - иерархия классов
Scala - types
X <: Y
All X: X <: Any
All x: Nothing <: X
def nothing: Nothing = { throw new Exception(“Throw exception, so return nothing”);}
Scala - functions
trait Function1[-X, +Y] extends PartialFunction[X, Y]{ def apply(x:X): Y def isDefinedAt(x:X) = true; }
Function0[X] : () => XFunction1[X,y] : (X) => Y / X => YFunction2[X,Y,Z] : (X,Y) => Z........
Scala - функции
(x:X)=> ..(expression)..
Абсолютно то-же самое с помощью объектного синтаксиса:
class MyFun extends Function[X,Y] { def apply(x:X) = ….. (expression) …. }
или даже, если мы хотим что-бы класс был анонимным:
new Function[X,Y]() { def apply(x:X) = ….. (expression) …. }
Scala - traits
trait A { def a = 1; }
trait B { def b = 2; }
class C extends A with B ;
val c = new C; c.b;
Scala - классы
• только у класса может быть конструктор
• только класс может быть инстациирован оператором new.
class C(x:Int) extends A with B { def c = x;}
Scala - ко/контр вариантность
trait Function1[-X, +Y] extends PartialFunction[X, Y]
• ковариантность: • scala: +X, Java: ? extends X, C#: out X
• контрвариантность: • scala: -X, Java: ? super X, C#: in X
• инвариантность • просто Х.
Scala - functions
class X(i : Int){ def method(y : Int) = y + i}
val x = X(2);
Сделать метод из функции:
• val f: (Int => Int) = x.method• val f = x.method _• val f = { (z:Int) => x.method(z) }
Scala - control flow (1)
• Последовательность {x; y} • if (if (x) y else z)• Циклы
o whileo for
for(x <- y) { ... } == y.foreach{ x =>... } for(x <- y if z) { ... } ==
y.filter(x=>z) foreach { x=> .. } for(x <- y) yield { ..} == y.map{ x => ... } for(x1 <- y1; x2 <- y2) == y.flatMap(x1=>y2.map{x2=>..}))
• выражения и вызовы функций:o f(x,y).. o x f y = x.f(y)
Scala - function calls
(1 to 100) foldLeft( _ + _)
• (1 to 100) == 1.to(100) = Range ..• (_ + _) == (x,y) => x + y• x foldLeft y == x.foldLeft(y)
• (x1, x2, ... xn) foldLeft f == f(..f(x1,x2), ..)),Xn)• def "+" (x:MyType) = ......
Scala case patterns
• ML - style pattern matching
x match { case pattern1 => statement1 case pattern2 => statement2 ... }
x match { case 1 => “One” case 2 => “Two” case _ => “Many” }
Scala case patterns 2
Регулярные выражения:
val dec = “””(\d+).(\d+)”””.r v match { case dec(x,y) => “decimal point, x=%s, y=%s”.format(x,y) case _ => “other” }
Проверка типов:
v match { case x: MyClass => doSomething(x) case x => doOther(x)}
Scala case classes (1)
case class Person(val firstName: String, val lastName: String){ def fullName = firstName + “ “ + lastName;}
А ПОТОМ:
v match { case Person(firstName, lastName) => ….. case Robot(ipAddr) => …}
Scala - case classes (2)
• Участвуют в сопоставлениях
• Сравниваются по значению а не по адресу (equals, hashCode)
• Генерируются несколько определенных методовo toString o copyo apply ...
Scala - сопряженные объекты
class MyClass { .................}
object MyClass {
....................... (методы, которые были бы static в java)
}
Scala -- functon calls (2)
Функциями могут быть любые последовательности символов
У параметров могут быть предопределенные значения по умолчанию
И синтаксис с наименованием аргументов.
val x = Person(“Jon”,”Smith”);val y = x.copy( firstName=”Tom” )
def copy(firstName:String = this.firstName, lastName:String = this.lastName) = new Person(firstName, lastName)
Scala - function calls (3)
Передача параметров
Обычная f(x: X)• по значению (примитивные типы: AnyVal)• по ссылке (ссылочные типы: AnyRef)• сначала вычисляются аргументы потом передаются
функцией
По "имени" f(x: => X)• аргументы вычисляются при обращении• выражение вызывается при каждом обращениии• "по имени" - Алгола 68 (сейчас бы назвали по другом)
Scala -- function calls
Зачем нужна передача по имени:
def cond[A](condition:Boolean, ifTrue: => A, ifElse: => A) = if(condition) ifTrue else ifElse ;
val x = cond(true, { println(“1”); 1 }, { println(“2”); 2 } )
Scala -- конструкции
break -- не часть языка, а часть библиотеки
val mybreaks = new Breaksimport mybreaks.{break, breakable}
breakable { for (...) { if (...) break }}
Scala -- пример мультиплексирования
Мультиплексирование ввода вывода - операционная система предоставляет вызов (select или poll) для ожидания/слушания ввода-вывода - нам хочется локально работать с одним клиентом в одном логическом потоке.
def fun(x: IO): A = {do sometjhing 1.. a = read(x) do sometjhing 2… write(x, b) do something 3 c = read(x) do something 4}
Scala - мультиплексирование (CPS)
def fun(x: IO): A = { do something 1.. a = read(x) do something 2… write(x, b) do something 3 c = read(x) do something 4}
class Continuation[A,IO]{ def fun(Context : IO) : Pair[Operation[IO], Continuation[A]] val context: Context def done: Boolean def result: Option[A] }
делает кусок работы и возвращает операцию и следующий кусок
Scala - мультиплексирование ввода/вывода (CPS) (2)
def fun(x: IO): A = { do something 1.. a = read(x) do something 2… write(x, b) do something 3 c = read(x) do something 4
}
class Cf0:Continuation[A] { def fun(Context, IO) = { do something1; (READ(x), Cf1); }....}class Cf1:Continuation[A] { def fun(ctx:Context, x: IO) = { val a = ctx.lastRead(x); do something2; (WRITE(x,b), Cf2); }.... }class Cf2:Continuation[A] { def fun(ctx: Context, x: IO) = { do something3; (READ(x), Cf3); }...}class Cf3:Continuation[A] { def fun(Context, IO) = { var c = ctx.lastRead(x); do-something4; (NONE, STOP); } def done = true; def result = context.getA;}
Scala - мультиплексирование ввода/вывода (cps) 3
val continuations:ConcurrentMap[IO, Continuation] while(true) { val fdset = select(...) for(x <- fdset) { continuations(x) match { case None => /* do nothing */ case Some(step) => val (op, nextStep) = step.fun(); if (step.done) { continuations.remove(x); } else { doOperaton(x,step.context); nextStep.context=step.context; continuations.put(x,nextStep); } } } }
Scala - CPS
def fun(x: IO): A = { do something 1.. a = read(x) do something 2… write(x, b) do something 3 c = read(x) do something 4
}
val funCont(x:IO) ={ x: => reset{ do sometjhing 1.. shift( cont => doRead(cont) ); do something2 .. shift( cont => doWrite(cont) ); do something3 .. shift( cont => doRead(cont) ); do something4 ...}}
multiplexor.doFun(funCont);
-- в cont -- все что после shift до конца блока reset.
Scala - actors.
Erlang style параллелизм
• "легковесные потоки"• очередь входных сообщений• асинхронная передача
Много реализаций -- тут синтаксис Akka-2.0
def MyActor extends Aktor { def receive = { case Message1 => "do something " case Message2 => do something other, sender!reply } }
Scala - actors.
2 основные операции
• tell. (fire & forget) o aktor ! message
• tell/ask (send and return feature)o actor !!! message
x !!! message => Future[X]
Future - get (ждать когда появится значение или пройдет timeout) - onComplete{ ..... } - ready ..
Scala - мультиплексирование ввода/вывода (Actors) (1)
def fun(x: IO): A = { do something 1.. a = read(x) do something 2… write(x, b) do something 3 c = read(x) do something 4}
class FunActor(x:IO, multiplexor:Actor)extends Actor ={
def receive = { do something 1 val fa = multiplexor !!! ReadMessage(x) do something 2 multiplexor ! WriteMessage(x,b) do something 3 val fc = multiplexor !!! ReadMessage(x) do something 4 }}
Scala - мультиплексирование ввода/вывода (Actors) (2)
def Multiplexor extends Actor{ val allReaders:ConcurrenctMap[IO,Queue[Actor]](); val allWriters:ConcurrentMap[IO,Queue[(Actor,Any)]]();
private val selectThread = new Thread() { while(true) { val fdset = select(....) for(x <- fdset) { allReaders.get(x) map { readers: Queue[Actor] => readers.dequeue match { case Some(reader) => reader!x case None => /* do nothing */ } }...... (для writers экономим место) } }
Scala - мультиплексирование ввода/вывода (Actors) (3)
....
def init = selectThread.start
def receive = { case ReadMessage(x) => atomic { add reader } case WriteMessage(x,b) => atomic { writers.add{ add writer } }}
• atomic -- STM (библиотека)
Scala -- ресурсы
http://www.scala-lang.org Учебники:• Programming scala http://programmingscala.com/• Twitter scala tutorial: http://twitter.github.com/scala_school/ • Stack Owerflow scala tutorial:http://stackoverflow.com/tags/scala/info
Группа пользователей scala в Украине: FB: Scala-Ukraine Google groups: Scala-UA
// Спасибо за внимание. Руслан Шевченко, ГрадСофт