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

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

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

• пишет на Java?	

• слышал о Scala?	

• пишет на Scala?	

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

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

• Scalable language	

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

• Статически ти...
ПЕРЕМЕННЫЕ И ЗНАЧЕНИЯ
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 =!
...
КЛАССЫ, ОБЪЕКТЫ И
ТРЕЙТЫ
trait Dumpable {!
def dump: String!
def dump(out: PrintStream) { out.print(dump) }!
}!
!
class Fo...
СИСТЕМА ТИПОВ
• Всё есть объект:Any,AnyVal,AnyRef	

• Кортежи:
scala> val tuple = (1, "a", true)!
tuple: (Int, String, Boo...
КТО ИСПОЛЬЗУЕТ 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-компилятор	

• Отлич...
ПРОИЗВОДИТЕЛЬНОСТЬ
• Какой код напишете, так и будет	

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

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

• Дружелюбное сообщество
ПРОДУКТИВНОСТЬ
Сложно вернуться на Java без боли
РАЗМЕР КОДА JAVA
public class Person {!
!
private final String name;!
private final int age;!
!
public Person(String name,...
РАЗМЕР КОДА SCALA
+ Метод-фабрика	

+ Метод copy	

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

• В поле зрени...
ВЫВОД ТИПОВ
• Scala	

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

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

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

• Извлечь тож...
OPTION
val capitals = Map("Russia" -> "Moscow",!
"France" -> "Paris")!
!
val a = capitals.get("Russia")!
// Some("Moscow")...
PATTERN MATCHING
sealed trait Shape!
case class Circle(radius: Double) extends Shape!
case class Rectangle(width: Double,!...
ПРОВЕРКА ПОЛНОТЫ
sealed trait Shape!
case class Circle(radius: Double) extends Shape!
case class Rectangle(width: Double,!...
FOR-EXPRESSIONS	

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

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

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

• Множественное наследов...
СЛОЖНОСТЬ
object Sized extends LowPrioritySized {!
implicit def sizedOps[Repr, L <: Nat](s : Sized[Repr, L])!
(implicit it...
ПРОСТОТА
def csv[N <: Nat](hdrs: Sized[Seq[String], N],!
rows: Sized[Seq[String], N]*) = ???!
!
csv(!
Sized("ID", "Name"),...
БОРЬБА СО СЛОЖНОСТЬЮ
• Обучение → делает сложное простым	

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

• Code re...
ENABLING LANGUAGE
FEATURES
implicit def intToString(x: Int): String = x.toString!
!
val x: String = 1
features.scala:7: im...
КАДРОВЫЙ ВОПРОС
• Перейти с Java на Scala для большинства не
составляет проблемы	

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

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

• Большая команда для не...
УГОВОРИЛ, КАК НАЧАТЬ
• Пишите на Scala так же как на Java	

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

• Поощряйте «хороший» скала-код: Option в...
ПРОБЛЕМЫ
• Более сложные концепции	

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

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

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

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

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

• О потоках и синхронизации заботится Akka	
...
ПРИМЕР AKKA
class Worker extends Actor {!
!
val db = DB.connect()!
!
override def postStop() {!
db.close()!
}!
!
def recei...
СУПЕРВИЗОР
class Supervisor extends Actor {!
!
override val supervisorStrategy =!
OneForOneStrategy(maxNrOfRetries = 10,!
...
POOLING
akka.actor.deployment {!
/parent/workerRouter {!
router = round-robin-pool!
nr-of-instances = 5!
}!
}!
!
val worke...
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)!
.sor...
БИБЛИОТЕКИTYPELEVEL
• Scalaz — упрощает программирование в
функциональном стиле (монады, функторы,
линзы и другие классы т...
SCALAZ: MONOIDS
val x = Map("a" -> List(1))!
!
val y = Map("a" -> List(2),!
"b" -> List(3))!
!
// or println(x mappend y)!...
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 ...
SCALATEST
$ scala -cp scalatest_2.11-2.2.0.jar org.scalatest.run ExampleSpec	
Discovery starting.	
Discovery completed in ...
ASSERTIONS
scala> assert(a == b || c >= d)
org.scalatest.exceptions.TestFailedException:
1 did not equal 2, and 3 was not ...
DIAGRAMMED ASSERTIONS
scala> assert(a == b || c >= d)
org.scalatest.exceptions.TestFailedException:
!
assert(a == b || c >...
СПАСИБО ЗА ВНИМАНИЕ	

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

• http://typesafe.com/platform/	

• http://typelevel.org/	

• http://www.scalatest.o...
Upcoming SlideShare
Loading in …5
×

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

926 views

Published on

Published in: Software
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
926
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
29
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

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

  1. 1. Что, как и зачем? Тимушев Роман
  2. 2. ОБО МНЕ • Scala с 2011 • Один из организаторов встреч Scala Moscow User Group • Работаю в Qubell
  3. 3. О ВАС • Кто из вас • пишет на Java? • слышал о Scala? • пишет на Scala? • слышал что такое монада? • понимает, что монада это моноид в категории эндофункторов?
  4. 4. ЧТО ТАКОЕ SCALA • Язык существует с 2003г. • Scalable language • Объединяет в себе OO и ФП-концепции • Статически типизирован • Компилируется в java-байткод • Open source
  5. 5. ПЕРЕМЕННЫЕ И ЗНАЧЕНИЯ var a: String = "foo"! a = "bar" // разрешено! ! val b: String = "foo"! b = "bar" // запрещено
  6. 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. 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. 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
  9. 9. КТО ИСПОЛЬЗУЕТ SCALA
  10. 10. ЧТО ЭТО, МОДА? If I were to pick a language today other than Java, it would be Scala. ! James Gosling,
 father of Java
  11. 11. ВЫБОР ЯЗЫКА • Совместимость • Производительность • Поддержка • Продуктивность
  12. 12. СОВМЕСТИМОСТЬ • Работает на платформе JVM • Windows, Mac, Linux,Android, кофеварки • Отличный JIT-компилятор • Отличный GC • Прозрачно интегрируется с Java-кодом • Смешанная компиляция • Можно использовать все доступные java-библиотеки • Старый код можно тоже не переписывать
  13. 13. ПРОИЗВОДИТЕЛЬНОСТЬ • Какой код напишете, так и будет • Производительность сравнима с Java • Обычно потребляет немного больше памяти, чем Java
  14. 14. ПОДДЕРЖКА • Коммерческая поддержка отTypesafe Inc. • Дружелюбное сообщество
  15. 15. ПРОДУКТИВНОСТЬ Сложно вернуться на Java без боли
  16. 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. 17. РАЗМЕР КОДА SCALA + Метод-фабрика + Метод copy + Деконструктор для pattern matching case class Person(name: String, age: Int)
  18. 18. РАЗМЕР ИМЕЕТ ЗНАЧЕНИЕ • Число ошибок на строку кода — константа слабо зависящая от языка программирования • В поле зрения человека попадает ограниченный объём кода • Человек может сфокусировать внимание на определённом объёме информации
  19. 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. 20. OPTION • Опциональное значение: None или Some(value) • Многие операции можно делать не извлекая значение • Извлечь тоже можно, но в отличие от null это делается явно • Все библиотеки используют этот тип • В Java 8 тоже есть Optional
  21. 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. 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. 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. 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. 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. 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. 27. AD-HOC POLYMORPHISM trait Pretty {! def toPrettyString: String! } Привет, Мартин. Ты не мог бы отнаследовать классы стандартной библиотеки от Pretty? Это очень важно для нас…
  28. 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. 29. AD-HOC POLYMORPHISM dump("Hello, Mera")! dump(List("a", "b"))! dump(42)! ! // ошибка компиляции! dump(1.0)
  30. 30. ДРУГИЕ ПЛЮШКИ • Ленивые значения • Именованые параметры • Значения параметров по- умолчанию • Множественное наследование • Структурные типы • Определение операторов • Ко- и контра-вариантность • Типы высших порядков • XML-литералы • Интерполяция строк • Макросы • …
  31. 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. 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. 33. БОРЬБА СО СЛОЖНОСТЬЮ • Обучение → делает сложное простым • Административные меры → запрет писать сложный код • Code review → понятен ли ваш код другим • Поддержка компилятора → явное подключение некоторых языковых конструкций
  34. 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. 35. КАДРОВЫЙ ВОПРОС • Перейти с Java на Scala для большинства не составляет проблемы • Готовых Scala-разработчиков мало, но их число растёт • Конкуренция на рынке вакансий ниже • Средний уровень Scala-разработчиков выше
  36. 36. КАДРОВЫЙ ВОПРОС • Нужна небольшая талантливая команда —
 Scala может оказаться предпочтительнее • Большая команда для несложных задач —
 Java будет лучшим выбором
  37. 37. УГОВОРИЛ, КАК НАЧАТЬ • Пишите на Scala так же как на Java • Начните с тестов • Поощряйте «хороший» скала-код: Option вместо null, иммутабельность • Желательно наличие эксперта в команде • Некоторые IDE умеют конвертировать Java код в Scala автоматически
  38. 38. ПРОБЛЕМЫ • Более сложные концепции • Медленная компиляция • Бинарная совместимость • Недостаточная поддержка в IDE
  39. 39. ПОЛЕЗНЫЕ БИБЛИОТЕКИ • Akka — многопоточные распределённые приложения • Slick — работа с базами данных • Shapeless, scalaz — выразительный и обобщённый код • Scalatest — удобное тестирование • SBT — система сборки
  40. 40. AKKA • Акторы — легковесные сущности, асинхронно обменивающиеся сообщениями • О потоках и синхронизации заботится Akka • Простой переход к распределённому приложению • Устойчивость к ошибкам
  41. 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. 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. 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. 44. REMOTING akka {! actor {! deployment {! /parent/worker {! remote =! "akka.tcp://ActorSystem@127.0.0.1:2553"! }! }! }! }
  45. 45. SLICK • Схема и запросы — обычный Scala-код • Работа с базой данных так же проста, как с обычными коллекциями • Запросы типобезопасны
  46. 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. 47. БИБЛИОТЕКИTYPELEVEL • Scalaz — упрощает программирование в функциональном стиле (монады, функторы, линзы и другие классы типов) • Shapeless — ещё более строгая типизация
  48. 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. 49. SHAPELESS:TYPE-SAFE CAST // опасно! x.asInstanceOf[Map[String, List[Int]]]! ! // безопасно! x.cast[Map[String, List[Int]]]
  50. 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. 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. 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. 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 ...
  54. 54. СПАСИБО ЗА ВНИМАНИЕ ВОПРОСЫ?
  55. 55. ССЫЛКИ • http://www.scala-lang.org/ • http://typesafe.com/platform/ • http://typelevel.org/ • http://www.scalatest.org/ • http://notes.implicit.ly/

×