Что, как и зачем?
Тимушев Роман
ОБО МНЕ
• Scala с 2011	

• Один из организаторов встреч Scala Moscow
User Group	

• Работаю в Qubell
О ВАС
• Кто из вас	

• пишет на Java?	

• слышал о Scala?	

• пишет на Scala?	

• слышал что такое монада?	

• понимает, что монада это моноид в категории эндофункторов?
ЧТО ТАКОЕ SCALA
• Язык существует с 2003г.	

• Scalable language	

• Объединяет в себе OO и ФП-концепции	

• Статически типизирован	

• Компилируется в java-байткод	

• Open source
ПЕРЕМЕННЫЕ И ЗНАЧЕНИЯ
var a: String = "foo"!
a = "bar" // разрешено!
!
val b: String = "foo"!
b = "bar" // запрещено
ФУНКЦИИ
def sum1(a: Int, b: Int): Int =!
a + b!
!
val sum2 =!
(a: Int, b: Int) => a + b!
!
val sum3: (Int, Int) => Int =!
(a, b) => a + b!
!
val sum4: (Int, Int) => Int =!
_ + _
КЛАССЫ, ОБЪЕКТЫ И
ТРЕЙТЫ
trait Dumpable {!
def dump: String!
def dump(out: PrintStream) { out.print(dump) }!
}!
!
class Foo extends Dumpable {!
override def dump = "Foo"!
}!
!
val foo = new Foo!
foo.dump(Console.out)!
!
object Bar extends Dumpable {!
override def dump = "Bar"!
}!
!
Bar.dump(Console.err)
СИСТЕМА ТИПОВ
• Всё есть объект:Any,AnyVal,AnyRef	

• Кортежи:
scala> val tuple = (1, "a", true)!
tuple: (Int, String, Boolean) = (1,a,true)!
!
scala> tuple._2!
res0: String = a!
!
scala> val (x, y, _) = tuple!
x: Int = 1!
y: String = a
КТО ИСПОЛЬЗУЕТ SCALA
ЧТО ЭТО,
МОДА?
If I were to pick a language
today other than Java, it would
be Scala.	

!
James Gosling,

father of Java
ВЫБОР ЯЗЫКА
• Совместимость	

• Производительность	

• Поддержка	

• Продуктивность
СОВМЕСТИМОСТЬ
• Работает на платформе JVM	

• Windows, Mac, Linux,Android, кофеварки	

• Отличный JIT-компилятор	

• Отличный GC	

• Прозрачно интегрируется с Java-кодом	

• Смешанная компиляция	

• Можно использовать все доступные java-библиотеки	

• Старый код можно тоже не переписывать
ПРОИЗВОДИТЕЛЬНОСТЬ
• Какой код напишете, так и будет	

• Производительность сравнима с Java	

• Обычно потребляет немного больше памяти,
чем Java
ПОДДЕРЖКА
• Коммерческая поддержка отTypesafe Inc.	

• Дружелюбное сообщество
ПРОДУКТИВНОСТЬ
Сложно вернуться на Java без боли
РАЗМЕР КОДА JAVA
public class Person {!
!
private final String name;!
private final int age;!
!
public Person(String name, int age) {!
this.name = name;!
this.age = age;!
}!
!
public String getName() {!
return name;!
}!
!
public int getAge() {!
return age;!
}!
!
@Override!
public String toString() {!
return "Person(" + name + ", " + age + ")";!
}!
!
@Override!
public boolean equals(Object o) {!
if (this == o) return true;!
if (o == null || getClass() != o.getClass()) return false;!
Person person = (Person) o;!
if (age != person.age) return false;!
if (name != null ? !name.equals(person.name) : person.name != null) return false;!
return true;!
}!
!
@Override!
public int hashCode() {!
int result = name != null ? name.hashCode() : 0;!
result = 31 * result + age;!
return result;!
}!
!
}
РАЗМЕР КОДА SCALA
+ Метод-фабрика	

+ Метод copy	

+ Деконструктор для pattern matching
case class Person(name: String, age: Int)
РАЗМЕР ИМЕЕТ ЗНАЧЕНИЕ
• Число ошибок на строку кода — константа
слабо зависящая от языка программирования	

• В поле зрения человека попадает
ограниченный объём кода	

• Человек может сфокусировать внимание на
определённом объёме информации
ВЫВОД ТИПОВ
• Scala	

! ! val list = new ListBuffer[String]()!
• Java	

! ! ArrayList<String> list = new ArrayList<>();!
• Scala	

! ! val set = new HashMap[String, Int]().keySet!
• Java	

! ! Set<String> set = new HashMap<String, String>().keySet();!
OPTION
• Опциональное значение: None или Some(value)	

• Многие операции можно делать не извлекая значение	

• Извлечь тоже можно, но в отличие от null это
делается явно	

• Все библиотеки используют этот тип	

• В Java 8 тоже есть Optional
OPTION
val capitals = Map("Russia" -> "Moscow",!
"France" -> "Paris")!
!
val a = capitals.get("Russia")!
// Some("Moscow")!
val b = capitals.get("Italy") // None!
!
a.map(_.toUpperCase) // Some("MOSCOW")!
b.map(_.toUpperCase) // None!
!
a.getOrElse("Unknown") // "Moscow"!
b.getOrElse("Unknown") // "Unknown"!
!
for (x <- a; y <- b) yield s"$x, $y" // None
PATTERN MATCHING
sealed trait Shape!
case class Circle(radius: Double) extends Shape!
case class Rectangle(width: Double,!
height: Double) extends Shape!
!
val description = shape match {!
case Rectangle(w, h) if w == h =>!
s"square, side $w"!
case Rectangle(w, h) =>!
s"rectangle, $w x $h"!
case Circle(r) =>!
s"circle, radius $r"!
}
ПРОВЕРКА ПОЛНОТЫ
sealed trait Shape!
case class Circle(radius: Double) extends Shape!
case class Rectangle(width: Double,!
height: Double) extends Shape!
!
val description = shape match {!
case Circle(r) =>!
s"circle, radius $r"!
}!
!
pm.scala:16: match may not be exhaustive.!
It would fail on the following input: Rectangle(_, _)!
val description = shape match {!
^
FOR-EXPRESSIONS	

case class City(name: String,!
streets: List[Street],!
population: Int)!
!
case class Street(name: String,!
sights: List[String])!
!
val cities: List[City]!
!
val plan = cities!
.filter(_.population > 1000)!
.flatMap(_.streets)!
.flatMap(s => s.sights.map(s -> _))
FOR-EXPRESSIONS
val plan = cities!
.filter(_.population > 1000)!
.flatMap(_.streets)!
.flatMap(s => s.sights.map(s -> _))!
!
val plan = for {!
city <- cities if city.population > 1000!
street <- city.streets!
poi <- street.sights!
} yield (street.name, poi)
НЕ ТОЛЬКО КОЛЛЕКЦИИ
def httpGet(url: String): Future[String] = ???!
!
def getPost(idx: Int): Future[String] =!
for {!
posts <- httpGet("http://localhost/posts")!
slug = posts.split("n")(idx)!
post <- httpGet(s"http://localhost/$slug")!
} yield post
AD-HOC POLYMORPHISM
trait Pretty {!
def toPrettyString: String!
}
Привет, Мартин. Ты не мог бы
отнаследовать классы стандартной
библиотеки от Pretty? Это очень
важно для нас…
AD-HOC POLYMORPHISM
implicit class StringPretty(x: String) extends Pretty {!
def toPrettyString = x!
}!
!
implicit class IntPretty(x: Int) extends Pretty {!
def toPrettyString = x.toString!
}!
!
implicit class ListPretty[T <% Pretty](x: List[T])!
extends Pretty {!
def toPrettyString =!
x.map(_.toPrettyString).mkString("[", ", ", "]")!
}
AD-HOC POLYMORPHISM
dump("Hello, Mera")!
dump(List("a", "b"))!
dump(42)!
!
// ошибка компиляции!
dump(1.0)
ДРУГИЕ ПЛЮШКИ
• Ленивые значения	

• Именованые параметры	

• Значения параметров по-
умолчанию	

• Множественное наследование	

• Структурные типы	

• Определение операторов	

• Ко- и контра-вариантность	

• Типы высших порядков	

• XML-литералы	

• Интерполяция строк	

• Макросы	

• …
СЛОЖНОСТЬ
object Sized extends LowPrioritySized {!
implicit def sizedOps[Repr, L <: Nat](s : Sized[Repr, L])!
(implicit itl: IsTraversableLike[Repr]): SizedOps[itl.A, Repr, L] =!
new SizedOps[itl.A, Repr, L](itl.conversion(s.unsized))!
!
def apply[CC[_]] = new SizedBuilder[CC]!
!
def apply[CC[_]]()!
(implicit cbf : CanBuildFrom[Nothing, Nothing, CC[Nothing]]) =!
new Sized[CC[Nothing], _0](cbf().result)!
!
def wrap[Repr, L <: Nat](r : Repr) = new Sized[Repr, L](r)!
!
def unapplySeq[Repr, L <: Nat](x : Sized[Repr, L]) = Some(x.unsized)!
}
ПРОСТОТА
def csv[N <: Nat](hdrs: Sized[Seq[String], N],!
rows: Sized[Seq[String], N]*) = ???!
!
csv(!
Sized("ID", "Name"),!
Sized("1", "Nikolay"),!
Sized("2", "Vasiliy"),!
// compile-time error!
Sized("3", "Ivan", "Ivanovich")!
)
БОРЬБА СО СЛОЖНОСТЬЮ
• Обучение → делает сложное простым	

• Административные меры → запрет писать
сложный код	

• Code review → понятен ли ваш код другим	

• Поддержка компилятора → явное подключение
некоторых языковых конструкций
ENABLING LANGUAGE
FEATURES
implicit def intToString(x: Int): String = x.toString!
!
val x: String = 1
features.scala:7: implicit conversion method
intToString should be enabled by making the implicit
value scala.language.implicitConversions visible.
import scala.language.implicitConversions
КАДРОВЫЙ ВОПРОС
• Перейти с Java на Scala для большинства не
составляет проблемы	

• Готовых Scala-разработчиков мало, но их число
растёт	

• Конкуренция на рынке вакансий ниже	

• Средний уровень Scala-разработчиков выше
КАДРОВЫЙ ВОПРОС
• Нужна небольшая талантливая команда —

Scala может оказаться предпочтительнее	

• Большая команда для несложных задач —

Java будет лучшим выбором
УГОВОРИЛ, КАК НАЧАТЬ
• Пишите на Scala так же как на Java	

• Начните с тестов	

• Поощряйте «хороший» скала-код: Option вместо null,
иммутабельность	

• Желательно наличие эксперта в команде	

• Некоторые IDE умеют конвертировать Java код в Scala
автоматически
ПРОБЛЕМЫ
• Более сложные концепции	

• Медленная компиляция	

• Бинарная совместимость	

• Недостаточная поддержка в IDE
ПОЛЕЗНЫЕ БИБЛИОТЕКИ
• Akka — многопоточные распределённые приложения	

• Slick — работа с базами данных	

• Shapeless, scalaz — выразительный и обобщённый код	

• Scalatest — удобное тестирование	

• SBT — система сборки
AKKA
• Акторы — легковесные сущности, асинхронно
обменивающиеся сообщениями	

• О потоках и синхронизации заботится Akka	

• Простой переход к распределённому
приложению	

• Устойчивость к ошибкам
ПРИМЕР AKKA
class Worker extends Actor {!
!
val db = DB.connect()!
!
override def postStop() {!
db.close()!
}!
!
def receive = {!
case Query(sql) => sender() ! db.query(sql)!
}!
!
}
СУПЕРВИЗОР
class Supervisor extends Actor {!
!
override val supervisorStrategy =!
OneForOneStrategy(maxNrOfRetries = 10,!
withinTimeRange = 1 minute) {!
case _: IOException => Restart!
case _: Exception => Escalate!
}!
!
val worker = context.actorOf(Props[Worker])!
!
def receive = {!
case q: Query => worker forward q!
}!
!
}
POOLING
akka.actor.deployment {!
/parent/workerRouter {!
router = round-robin-pool!
nr-of-instances = 5!
}!
}!
!
val workers = context.actorOf(!
FromConfig.props(Props[Worker]),!
"workerRouter"!
)
REMOTING
akka {!
actor {!
deployment {!
/parent/worker {!
remote =!
"akka.tcp://ActorSystem@127.0.0.1:2553"!
}!
}!
}!
}
SLICK
• Схема и запросы — обычный Scala-код	

• Работа с базой данных так же проста, как с
обычными коллекциями	

• Запросы типобезопасны
ПРИМЕР SLICK
// select NAME from COFFEES !
// where PRICE < 10.0!
// order by NAME!
coffees!
.filter(_.price < 10.0)!
.sortBy(_.name)!
.map(_.name)!
.list!
!
// Seq[String]("Cappuccino", "Espresso")
БИБЛИОТЕКИTYPELEVEL
• Scalaz — упрощает программирование в
функциональном стиле (монады, функторы,
линзы и другие классы типов)	

• Shapeless — ещё более строгая типизация
SCALAZ: MONOIDS
val x = Map("a" -> List(1))!
!
val y = Map("a" -> List(2),!
"b" -> List(3))!
!
// or println(x mappend y)!
println(x |+| y)!
!
"Map(a -> List(1, 2), b -> List(3))"
SHAPELESS:TYPE-SAFE CAST
// опасно!
x.asInstanceOf[Map[String, List[Int]]]!
!
// безопасно!
x.cast[Map[String, List[Int]]]
SCALATEST
class ExampleSpec extends FreeSpec with Matchers {!
"A Stack" should "pop values in last-in-first-out order" in {!
val stack = new Stack[Int]!
stack.push(1)!
stack.push(2)!
stack.pop() should be (2)!
stack.pop() should be (1)!
}!
it should "throw NoSuchElementException if an empty stack is popped" in {!
val emptyStack = new Stack[Int]!
a [NoSuchElementException] should be thrownBy {!
emptyStack.pop()!
} !
}!
}
SCALATEST
$ scala -cp scalatest_2.11-2.2.0.jar org.scalatest.run ExampleSpec	
Discovery starting.	
Discovery completed in 21 milliseconds.	
Run starting. Expected test count is: 2	
ExampleSpec:	
A Stack	
- should pop values in last-in-first-out order	
- should throw NoSuchElementException if an empty stack is popped	
Run completed in 76 milliseconds.	
Total number of tests run: 2	
Suites: completed 1, aborted 0	
Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 0	
All tests passed.
ASSERTIONS
scala> assert(a == b || c >= d)
org.scalatest.exceptions.TestFailedException:
1 did not equal 2, and 3 was not greater than or equal to 4
at ...
!
scala> assert(Some(2).isEmpty)
org.scalatest.exceptions.TestFailedException:
Some(2) was not empty
at ...
DIAGRAMMED ASSERTIONS
scala> assert(a == b || c >= d)
org.scalatest.exceptions.TestFailedException:
!
assert(a == b || c >= d)
| | | | | | |
1 | 2 | 3 | 4
| | false
| false
false
!
at ...
СПАСИБО ЗА ВНИМАНИЕ	

ВОПРОСЫ?
ССЫЛКИ
• http://www.scala-lang.org/	

• http://typesafe.com/platform/	

• http://typelevel.org/	

• http://www.scalatest.org/	

• http://notes.implicit.ly/

More Related Content

PPTX
Scala для всех (РИФ 2015)
PDF
Павел Павлов - Scala для профессионалов - Joker 2013
PDF
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
PPTX
Javascript 1
PDF
Андрей Карпов, Приватные байки от разработчиков анализатора кода
PDF
Haskell
PPTX
Clojure: Lisp for the modern world (русская версия)
PPTX
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
Scala для всех (РИФ 2015)
Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Javascript 1
Андрей Карпов, Приватные байки от разработчиков анализатора кода
Haskell
Clojure: Lisp for the modern world (русская версия)
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...

What's hot (18)

PDF
Scala and LiftWeb presentation (Russian)
PDF
Внешние языки DSL на funcparserlib
PDF
Groovy presentation.
PDF
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
PDF
Михаил Давыдов: JavaScript. Базовые знания
PDF
Лекция 11. Тестирование.
PPTX
Александр Фокин, Рефлексия в C++
PDF
Лекция 12. Быстрее, Python, ещё быстрее.
PDF
Formal verification of C code
PPTX
C#. От основ к эффективному коду
PDF
AOT для Java: Мифы и Challenges
PDF
модель акторов и C++ что, зачем и как ?
PDF
Лекция 1. Начало.
PDF
Лекция 2. Всё, что вы хотели знать о функциях в Python.
PDF
Лекция 4. Строки, байты, файлы и ввод/вывод.
PDF
Making of external DSL for Django ORM - Павел Петлинский, Rambler&Co
PDF
Язык программирования Scala / Владимир Успенский (TCS Bank)
PDF
Лекция 6. Классы 1.
Scala and LiftWeb presentation (Russian)
Внешние языки DSL на funcparserlib
Groovy presentation.
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
Михаил Давыдов: JavaScript. Базовые знания
Лекция 11. Тестирование.
Александр Фокин, Рефлексия в C++
Лекция 12. Быстрее, Python, ещё быстрее.
Formal verification of C code
C#. От основ к эффективному коду
AOT для Java: Мифы и Challenges
модель акторов и C++ что, зачем и как ?
Лекция 1. Начало.
Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 4. Строки, байты, файлы и ввод/вывод.
Making of external DSL for Django ORM - Павел Петлинский, Rambler&Co
Язык программирования Scala / Владимир Успенский (TCS Bank)
Лекция 6. Классы 1.
Ad

Viewers also liked (20)

PDF
PDF
PDF
PDF
PDF
PDF
PDF
PDF
PDF
Scala for android
PDF
Under the hood of scala implicits (Scala eXchange 2014)
PDF
Scala lecture #4
PDF
PDF
Under the hood of scala implicits (kl10tch 10.03.2015)
PDF
Scala training
PDF
Feature suggester
PDF
Scala for android
Under the hood of scala implicits (Scala eXchange 2014)
Scala lecture #4
Under the hood of scala implicits (kl10tch 10.03.2015)
Scala training
Feature suggester
Ad

Similar to Scala: что, как и зачем? (20)

PPTX
Зачем нужна Scala?
PDF
Lift, play, akka, rails part1
PDF
Scala
PDF
Scala, Play Framework и SBT для быстрого прототипирования и разработки веб-пр...
ODP
PDF
Scala EE: Myth or Reality?
PDF
Scala, SBT & Play! for Rapid Application Development
PDF
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
PDF
Scala for Android Explained
PPTX
Kotlin
PDF
Kotlin на практике
ODP
Scala: introduction
PDF
Scala Rock-Painting
PPTX
PPTX
PPT
Лекция 6
PDF
Scala on android
PPT
Куда уходит память?
PPTX
[Expert Fridays] Java MeetUp - Борис Ташкулов (Teamlead Enterprise): "Почему ...
PPT
Характерные черты функциональных языков программирования
Зачем нужна Scala?
Lift, play, akka, rails part1
Scala
Scala, Play Framework и SBT для быстрого прототипирования и разработки веб-пр...
Scala EE: Myth or Reality?
Scala, SBT & Play! for Rapid Application Development
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
Scala for Android Explained
Kotlin
Kotlin на практике
Scala: introduction
Scala Rock-Painting
Лекция 6
Scala on android
Куда уходит память?
[Expert Fridays] Java MeetUp - Борис Ташкулов (Teamlead Enterprise): "Почему ...
Характерные черты функциональных языков программирования

Scala: что, как и зачем?

  • 1. Что, как и зачем? Тимушев Роман
  • 2. ОБО МНЕ • Scala с 2011 • Один из организаторов встреч Scala Moscow User Group • Работаю в Qubell
  • 3. О ВАС • Кто из вас • пишет на Java? • слышал о Scala? • пишет на Scala? • слышал что такое монада? • понимает, что монада это моноид в категории эндофункторов?
  • 4. ЧТО ТАКОЕ SCALA • Язык существует с 2003г. • Scalable language • Объединяет в себе OO и ФП-концепции • Статически типизирован • Компилируется в java-байткод • Open source
  • 5. ПЕРЕМЕННЫЕ И ЗНАЧЕНИЯ var a: String = "foo"! a = "bar" // разрешено! ! val b: String = "foo"! b = "bar" // запрещено
  • 6. ФУНКЦИИ def sum1(a: Int, b: Int): Int =! a + b! ! val sum2 =! (a: Int, b: Int) => a + b! ! val sum3: (Int, Int) => Int =! (a, b) => a + b! ! val sum4: (Int, Int) => Int =! _ + _
  • 7. КЛАССЫ, ОБЪЕКТЫ И ТРЕЙТЫ trait Dumpable {! def dump: String! def dump(out: PrintStream) { out.print(dump) }! }! ! class Foo extends Dumpable {! override def dump = "Foo"! }! ! val foo = new Foo! foo.dump(Console.out)! ! object Bar extends Dumpable {! override def dump = "Bar"! }! ! Bar.dump(Console.err)
  • 8. СИСТЕМА ТИПОВ • Всё есть объект:Any,AnyVal,AnyRef • Кортежи: scala> val tuple = (1, "a", true)! tuple: (Int, String, Boolean) = (1,a,true)! ! scala> tuple._2! res0: String = a! ! scala> val (x, y, _) = tuple! x: Int = 1! y: String = a
  • 10. ЧТО ЭТО, МОДА? If I were to pick a language today other than Java, it would be Scala. ! James Gosling,
 father of Java
  • 11. ВЫБОР ЯЗЫКА • Совместимость • Производительность • Поддержка • Продуктивность
  • 12. СОВМЕСТИМОСТЬ • Работает на платформе JVM • Windows, Mac, Linux,Android, кофеварки • Отличный JIT-компилятор • Отличный GC • Прозрачно интегрируется с Java-кодом • Смешанная компиляция • Можно использовать все доступные java-библиотеки • Старый код можно тоже не переписывать
  • 13. ПРОИЗВОДИТЕЛЬНОСТЬ • Какой код напишете, так и будет • Производительность сравнима с Java • Обычно потребляет немного больше памяти, чем Java
  • 14. ПОДДЕРЖКА • Коммерческая поддержка отTypesafe Inc. • Дружелюбное сообщество
  • 16. РАЗМЕР КОДА JAVA public class Person {! ! private final String name;! private final int age;! ! public Person(String name, int age) {! this.name = name;! this.age = age;! }! ! public String getName() {! return name;! }! ! public int getAge() {! return age;! }! ! @Override! public String toString() {! return "Person(" + name + ", " + age + ")";! }! ! @Override! public boolean equals(Object o) {! if (this == o) return true;! if (o == null || getClass() != o.getClass()) return false;! Person person = (Person) o;! if (age != person.age) return false;! if (name != null ? !name.equals(person.name) : person.name != null) return false;! return true;! }! ! @Override! public int hashCode() {! int result = name != null ? name.hashCode() : 0;! result = 31 * result + age;! return result;! }! ! }
  • 17. РАЗМЕР КОДА SCALA + Метод-фабрика + Метод copy + Деконструктор для pattern matching case class Person(name: String, age: Int)
  • 18. РАЗМЕР ИМЕЕТ ЗНАЧЕНИЕ • Число ошибок на строку кода — константа слабо зависящая от языка программирования • В поле зрения человека попадает ограниченный объём кода • Человек может сфокусировать внимание на определённом объёме информации
  • 19. ВЫВОД ТИПОВ • Scala ! ! val list = new ListBuffer[String]()! • Java ! ! ArrayList<String> list = new ArrayList<>();! • Scala ! ! val set = new HashMap[String, Int]().keySet! • Java ! ! Set<String> set = new HashMap<String, String>().keySet();!
  • 20. OPTION • Опциональное значение: None или Some(value) • Многие операции можно делать не извлекая значение • Извлечь тоже можно, но в отличие от null это делается явно • Все библиотеки используют этот тип • В Java 8 тоже есть Optional
  • 21. OPTION val capitals = Map("Russia" -> "Moscow",! "France" -> "Paris")! ! val a = capitals.get("Russia")! // Some("Moscow")! val b = capitals.get("Italy") // None! ! a.map(_.toUpperCase) // Some("MOSCOW")! b.map(_.toUpperCase) // None! ! a.getOrElse("Unknown") // "Moscow"! b.getOrElse("Unknown") // "Unknown"! ! for (x <- a; y <- b) yield s"$x, $y" // None
  • 22. PATTERN MATCHING sealed trait Shape! case class Circle(radius: Double) extends Shape! case class Rectangle(width: Double,! height: Double) extends Shape! ! val description = shape match {! case Rectangle(w, h) if w == h =>! s"square, side $w"! case Rectangle(w, h) =>! s"rectangle, $w x $h"! case Circle(r) =>! s"circle, radius $r"! }
  • 23. ПРОВЕРКА ПОЛНОТЫ sealed trait Shape! case class Circle(radius: Double) extends Shape! case class Rectangle(width: Double,! height: Double) extends Shape! ! val description = shape match {! case Circle(r) =>! s"circle, radius $r"! }! ! pm.scala:16: match may not be exhaustive.! It would fail on the following input: Rectangle(_, _)! val description = shape match {! ^
  • 24. FOR-EXPRESSIONS case class City(name: String,! streets: List[Street],! population: Int)! ! case class Street(name: String,! sights: List[String])! ! val cities: List[City]! ! val plan = cities! .filter(_.population > 1000)! .flatMap(_.streets)! .flatMap(s => s.sights.map(s -> _))
  • 25. FOR-EXPRESSIONS val plan = cities! .filter(_.population > 1000)! .flatMap(_.streets)! .flatMap(s => s.sights.map(s -> _))! ! val plan = for {! city <- cities if city.population > 1000! street <- city.streets! poi <- street.sights! } yield (street.name, poi)
  • 26. НЕ ТОЛЬКО КОЛЛЕКЦИИ def httpGet(url: String): Future[String] = ???! ! def getPost(idx: Int): Future[String] =! for {! posts <- httpGet("http://localhost/posts")! slug = posts.split("n")(idx)! post <- httpGet(s"http://localhost/$slug")! } yield post
  • 27. AD-HOC POLYMORPHISM trait Pretty {! def toPrettyString: String! } Привет, Мартин. Ты не мог бы отнаследовать классы стандартной библиотеки от Pretty? Это очень важно для нас…
  • 28. AD-HOC POLYMORPHISM implicit class StringPretty(x: String) extends Pretty {! def toPrettyString = x! }! ! implicit class IntPretty(x: Int) extends Pretty {! def toPrettyString = x.toString! }! ! implicit class ListPretty[T <% Pretty](x: List[T])! extends Pretty {! def toPrettyString =! x.map(_.toPrettyString).mkString("[", ", ", "]")! }
  • 29. AD-HOC POLYMORPHISM dump("Hello, Mera")! dump(List("a", "b"))! dump(42)! ! // ошибка компиляции! dump(1.0)
  • 30. ДРУГИЕ ПЛЮШКИ • Ленивые значения • Именованые параметры • Значения параметров по- умолчанию • Множественное наследование • Структурные типы • Определение операторов • Ко- и контра-вариантность • Типы высших порядков • XML-литералы • Интерполяция строк • Макросы • …
  • 31. СЛОЖНОСТЬ object Sized extends LowPrioritySized {! implicit def sizedOps[Repr, L <: Nat](s : Sized[Repr, L])! (implicit itl: IsTraversableLike[Repr]): SizedOps[itl.A, Repr, L] =! new SizedOps[itl.A, Repr, L](itl.conversion(s.unsized))! ! def apply[CC[_]] = new SizedBuilder[CC]! ! def apply[CC[_]]()! (implicit cbf : CanBuildFrom[Nothing, Nothing, CC[Nothing]]) =! new Sized[CC[Nothing], _0](cbf().result)! ! def wrap[Repr, L <: Nat](r : Repr) = new Sized[Repr, L](r)! ! def unapplySeq[Repr, L <: Nat](x : Sized[Repr, L]) = Some(x.unsized)! }
  • 32. ПРОСТОТА def csv[N <: Nat](hdrs: Sized[Seq[String], N],! rows: Sized[Seq[String], N]*) = ???! ! csv(! Sized("ID", "Name"),! Sized("1", "Nikolay"),! Sized("2", "Vasiliy"),! // compile-time error! Sized("3", "Ivan", "Ivanovich")! )
  • 33. БОРЬБА СО СЛОЖНОСТЬЮ • Обучение → делает сложное простым • Административные меры → запрет писать сложный код • Code review → понятен ли ваш код другим • Поддержка компилятора → явное подключение некоторых языковых конструкций
  • 34. ENABLING LANGUAGE FEATURES implicit def intToString(x: Int): String = x.toString! ! val x: String = 1 features.scala:7: implicit conversion method intToString should be enabled by making the implicit value scala.language.implicitConversions visible. import scala.language.implicitConversions
  • 35. КАДРОВЫЙ ВОПРОС • Перейти с Java на Scala для большинства не составляет проблемы • Готовых Scala-разработчиков мало, но их число растёт • Конкуренция на рынке вакансий ниже • Средний уровень Scala-разработчиков выше
  • 36. КАДРОВЫЙ ВОПРОС • Нужна небольшая талантливая команда —
 Scala может оказаться предпочтительнее • Большая команда для несложных задач —
 Java будет лучшим выбором
  • 37. УГОВОРИЛ, КАК НАЧАТЬ • Пишите на Scala так же как на Java • Начните с тестов • Поощряйте «хороший» скала-код: Option вместо null, иммутабельность • Желательно наличие эксперта в команде • Некоторые IDE умеют конвертировать Java код в Scala автоматически
  • 38. ПРОБЛЕМЫ • Более сложные концепции • Медленная компиляция • Бинарная совместимость • Недостаточная поддержка в IDE
  • 39. ПОЛЕЗНЫЕ БИБЛИОТЕКИ • Akka — многопоточные распределённые приложения • Slick — работа с базами данных • Shapeless, scalaz — выразительный и обобщённый код • Scalatest — удобное тестирование • SBT — система сборки
  • 40. AKKA • Акторы — легковесные сущности, асинхронно обменивающиеся сообщениями • О потоках и синхронизации заботится Akka • Простой переход к распределённому приложению • Устойчивость к ошибкам
  • 41. ПРИМЕР AKKA class Worker extends Actor {! ! val db = DB.connect()! ! override def postStop() {! db.close()! }! ! def receive = {! case Query(sql) => sender() ! db.query(sql)! }! ! }
  • 42. СУПЕРВИЗОР class Supervisor extends Actor {! ! override val supervisorStrategy =! OneForOneStrategy(maxNrOfRetries = 10,! withinTimeRange = 1 minute) {! case _: IOException => Restart! case _: Exception => Escalate! }! ! val worker = context.actorOf(Props[Worker])! ! def receive = {! case q: Query => worker forward q! }! ! }
  • 43. POOLING akka.actor.deployment {! /parent/workerRouter {! router = round-robin-pool! nr-of-instances = 5! }! }! ! val workers = context.actorOf(! FromConfig.props(Props[Worker]),! "workerRouter"! )
  • 44. REMOTING akka {! actor {! deployment {! /parent/worker {! remote =! "akka.tcp://ActorSystem@127.0.0.1:2553"! }! }! }! }
  • 45. SLICK • Схема и запросы — обычный Scala-код • Работа с базой данных так же проста, как с обычными коллекциями • Запросы типобезопасны
  • 46. ПРИМЕР SLICK // select NAME from COFFEES ! // where PRICE < 10.0! // order by NAME! coffees! .filter(_.price < 10.0)! .sortBy(_.name)! .map(_.name)! .list! ! // Seq[String]("Cappuccino", "Espresso")
  • 47. БИБЛИОТЕКИTYPELEVEL • Scalaz — упрощает программирование в функциональном стиле (монады, функторы, линзы и другие классы типов) • Shapeless — ещё более строгая типизация
  • 48. SCALAZ: MONOIDS val x = Map("a" -> List(1))! ! val y = Map("a" -> List(2),! "b" -> List(3))! ! // or println(x mappend y)! println(x |+| y)! ! "Map(a -> List(1, 2), b -> List(3))"
  • 49. SHAPELESS:TYPE-SAFE CAST // опасно! x.asInstanceOf[Map[String, List[Int]]]! ! // безопасно! x.cast[Map[String, List[Int]]]
  • 50. SCALATEST class ExampleSpec extends FreeSpec with Matchers {! "A Stack" should "pop values in last-in-first-out order" in {! val stack = new Stack[Int]! stack.push(1)! stack.push(2)! stack.pop() should be (2)! stack.pop() should be (1)! }! it should "throw NoSuchElementException if an empty stack is popped" in {! val emptyStack = new Stack[Int]! a [NoSuchElementException] should be thrownBy {! emptyStack.pop()! } ! }! }
  • 51. SCALATEST $ scala -cp scalatest_2.11-2.2.0.jar org.scalatest.run ExampleSpec Discovery starting. Discovery completed in 21 milliseconds. Run starting. Expected test count is: 2 ExampleSpec: A Stack - should pop values in last-in-first-out order - should throw NoSuchElementException if an empty stack is popped Run completed in 76 milliseconds. Total number of tests run: 2 Suites: completed 1, aborted 0 Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 0 All tests passed.
  • 52. ASSERTIONS scala> assert(a == b || c >= d) org.scalatest.exceptions.TestFailedException: 1 did not equal 2, and 3 was not greater than or equal to 4 at ... ! scala> assert(Some(2).isEmpty) org.scalatest.exceptions.TestFailedException: Some(2) was not empty at ...
  • 53. DIAGRAMMED ASSERTIONS scala> assert(a == b || c >= d) org.scalatest.exceptions.TestFailedException: ! assert(a == b || c >= d) | | | | | | | 1 | 2 | 3 | 4 | | false | false false ! at ...
  • 55. ССЫЛКИ • http://www.scala-lang.org/ • http://typesafe.com/platform/ • http://typelevel.org/ • http://www.scalatest.org/ • http://notes.implicit.ly/