Участник:Orionll/Scala
Материал из Lurkmore
Эта статья находится на доработке. Эта статья всё ещё не взлетела и не соответствует нынешним реалиям /lm/. Но добрый Orionll приютил её в своём личном пространстве, и теперь она может Модераторам: выпустить Дата последней правки страницы: 16.09.2015 |
Scala (Скала, скакалка) — хипстофрикоэнтерпрайзный мультипарадигменный язык программирования со статической типизацией, продукт деятельности немецкого профессора Мартина Одерски. Позиционируется как замена языка Java™©®, что вызывает глубокое неудовольствие у сторонников как Java, так и Кложуры, другого перспективного языка программирования под JVM.
Содержание |
История
В начале 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 получаются зачастую более громоздкими, чем например в Хаскеле, потому что часто приходится явно указывать типы параметризованных классов.
Фичи языка
- Функции ничем не хуже, чем другие типы данных. Функции могут быть объявлены внутри других функций, могут возвращаться из функций и приниматься в качестве их аргументов.
- Вменяемые обобщенные типы
class Tree[Type] { var node: Type = _ var left : Tree[Type] = _ var right : Tree[Type] = _ }
А вот класс Tree, который принимает в качестве параметра типа только числовые типы, то есть
любой из числовых типов Scala и их потомковclass NumericTree[Type <% AnyVal] { var node : Type = _ var left : Tree[Type] = _ var right : Tree[Type] = _ }
- 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 метода. Пример использования:
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
(неявно).
Где используется
Ви таки будете смеяться, но — в банках. То есть там же, где и сракле.
Мемы
[ + ] Любой программист без словаря поймёт, что такое Orionll/Scala
|
|||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|