Персональные инструменты
Счётчики

Участник:Orionll/Scala

Материал из Lurkmore
Перейти к: навигация, поиск
|
Recycle.pngЭта статья находится на доработке.
Эта статья всё ещё не взлетела и не соответствует нынешним реалиям /lm/. Но добрый Orionll приютил её в своём личном пространстве, и теперь она может тихо гнить неспешно дописываться здесь вечно.Дата последней правки страницы: 26.11.2013
«

Могу честно сказать, что если бы кто-нибудь мне показал книгу "Programming in Scala by Martin Odersky, Lex Spoon & Bill Venners" в 2003 году, то я возможно бы никогда не создал Groovy

»
— Джеймс Стрэчен, создатель языка Groovy
«

Haskell, Scala могут чморить всех. OCaml может чморить всех кроме Haskell и Scala. Erlang и Clojure могут чморить всех кроме Haskell, Scala, OCaml.

»
— Namdak Tonpa

Scala (Скала, скакалка) — хипстофрикоэнтерпрайзный мультипарадигменный язык программирования со статической типизацией, созданный в 2003-м году немецким профессором Мартином Одерски. Позиционируется как замена языка Java, что вызывает глубокое неудовольствие у сторонников Clojure, другого перспективного языка программирования под JVM.

Ниша Scala

Содержание

История

В начале 2000-х Одерски работал над языком Pizza, который был создан как площадка для экспериментов над языком Java. В Pizza Одерски сделал параметрический полиморфизм, функции-объекты первого класса, паттерн-матчинг и прочую функциональщину. Однако только дженерики в итоге перекочевали в Джаву, а от остального отказались. Дабы не пропадать добру, Одерски решил взять свои наработки и создал в 2003 году первый компилятор языка Scala, который как и Java, компилируется в байт-код JVM.

Мартин

Java++

По идее, язык Scala задумывался таким образом, чтобы на нём могли писать абсолютно все, начиная от нубов-хеллоуворлдщиков и заканчивая продвинутыми девелоперами-задротами, не понаслышке знающими, что такое теоркат, функторы и монады (в отличие от Haskell, который способны осилить только последние). К несчастью, Скала не защищает от возможности писать гавнокод на ней, и жабакодеры, пересаживающиеся на Скалу, продолжают писать в своём привычном джава-стайле. Поэтому в команде должен быть хотя бы один человек, который хорошо знает Скалу и который давал бы пизды остальным.

Ходят слухи [1], что Scala для Java есть ничто иное как C++ для C. Но никто (даже труп страуса) в совершенстве не знает C++. Каждая C++ команда изобретает свой C++ диалект и чморит другие команды, которые пишут на "другом C++". Такая же участь может постигнуть и Scala. Однако есть и противоположное мнение [2], что "в отличие от C++, Scala становится тем проще, чем дальше её изучаешь".

В любом случае, факт остается фактом, что одну и ту же задачу на Scala можно решить стопицот способами, даже если это простой "Hello World", и этот аргумент явно не в пользу Scala.

ООП + ФП

Scala — это ООП + ФП. Т.е. можно писать и ООП, можно и ФП. А некоторые скалолазы умудряются даже неплохо совмещать.

ООП в Скале отличается от ООП в жабе/C#: в Скале есть множественное наследование. Но множественное наследование это правильное, не как в плюсах — реализуется через trait'ы (они же примеси — интерфейсы, у которых можно реализовывать методы), причем порядок наследования от примесей важен (!). Гуглить на тему stackable modifications, если интересно.

ФП в Скале также отличается от ФП в ML, Haskell, F# и других чисто функциональных (без ООП) языках со статической типизацией. Главное отличие — отсутствие type union'ов (которое, хотя, легко имитируется через наследование и case-классы). Второе — это отсутствие полного вывода типов, из-за чего программы на Scala получаются зачастую более громоздкими, чем например в Хаскеле, потому что часто приходится явно указывать типы параметризованных классов.

Фичи языка

  • Функции ничем не хуже, чем другие типы данных. Функции могут быть объявлены внутри других функций, могут возвращаться из функций и приниматься в качестве их аргументов.
  • case-классы и паттерн-матчинг:
sealed trait Tree
case class Leaf(val v: Int) extends Tree
case class Node(val left: Tree, val right: Tree) extends Tree
 
/** Посчитать сумму дерева */
def sum(tree: Tree): Int = tree match {
  case Leaf(v) => v
  case Node(left, right) => sum(left) + sum(right)
}

Аналогичный жабакод занял бы в 10 раз больше места.

sealed означает, что иерархия закрыта и никакой анонимус не сможет отнаследоваться от trait'а Tree. case означает, что Scala-компайлер нагенерит для классов Leaf и Node кучу шаблонных методов типа equals, hashCode (чтобы сравнивать) и apply (чтобы не писать new).

Особенно крутая вещь — можно матчиться по вложенным паттернам (например, Node(Leaf(5), Leaf(v))).

  • object — встроенный в язык правильный синглтон (без всей этой вашей double checked locking и другой громоздкой хуиты)
  • lazy — инициализация происходит в момент первого использования
  • for-компрехеншены. Например, найти названия всех книг, среди авторов которых есть тот, чья фамилия начинается со слова Gosling:
for {
  b <- books;
  a <- b.authors
  if a startsWith "Gosling"
} yield b.title
  • В Scala есть implicit'ы, с помощью которых можно неявно привести что угодно к чему угодно. При чрезмерном использовании делает код абсолютно нечитаемым.
  • Мощная иерархия коллекций с кучей методов. В одном только интерфейсе Iterable over 104 метода. Пример использования:
Создаем список из чисел от 1 до 20 и делим его на два подсписка: с четными и нечетными элементами
val (odd, even) = (1 to 20).toList.partition(f => f % 2 == 0)
, а затем считаем их суммы: можно так
val sumEven = even.fold(0)(_ + _)
val sumOdd = odd.fold(0)(_ + _)
, а можно и так
val sumEven = even.sum;
val sumOdd = odd.sum;

Анонимусу может быть интересно, каким образом работает odd.sum. Ответ прост: есть implicit из Int в специальный класс Numeric, а метод sum принимает на вход этот самый Numeric (неявно).