Развенчание мифов Scala

Каковы наиболее распространенные заблуждения относительно языка Scala и какие контр-примеры существуют для них?

ОБНОВЛЕНИЕ

Я больше думал о различных претензиях, которые я видел, таких как "Scala является динамически типизированным" и "Scala является языком сценариев".

Я принимаю, что "Scala is [Simple/Complex]" может считаться мифом, но это также точка зрения, которая очень зависит от контекста. Мое личное убеждение в том, что те же самые функции, которые могут сделать Scala, кажутся либо простыми, либо сложными, в зависимости от того, кто их использует. В конечном счете, язык просто предлагает абстракции, и именно так они используются, что формирует восприятие.

Не только это, но он имеет определенную тенденцию к разжиганию аргументов, и я еще не видел, чтобы кто-то менял решительную точку зрения на эту тему...

Ответ 1

Миф: Scala поддерживает перегрузку оператора.

Фактически, Scala имеет очень гибкие правила именования методов и синтаксис infix для вызова метода, со специальными правилами для определения приоритета метода, когда синтаксис infix используется с "операторами". Это тонкое различие имеет критические последствия для полезности и возможности злоупотребления этой языковой функцией по сравнению с реальной перегрузкой оператора (a la С++), как более подробно объяснено в ответе Джеймса Ири на этот вопрос.

Ответ 3

Я не согласен с аргументом, что Scala сложно, потому что вы можете использовать очень продвинутые функции, чтобы делать с ним тяжелые вещи. Масштабируемость Scala означает, что вы можете писать абстракции DSL и API высокого уровня в самом Scala, которые в противном случае нуждаются в расширении языка. Поэтому, чтобы быть справедливым, вам нужно сравнить библиотеки Scala с другими компиляторами языков. Люди не говорят, что С# сложно, потому что (я полагаю, у меня нет первых знаний) компилятор С# довольно непроницаем. Для Scala все это открыто. Но нам нужно понять, что большинству людей не нужно писать код на этом уровне, и они не должны этого делать.

Ответ 4

Я думаю, что распространенное заблуждение среди многих разработчиков scala, у EPFL (и самого себя, Кевина) заключается в том, что "scala - простой язык". Обычно аргумент имеет следующий вид:

  • scala имеет несколько ключевых слов
  • scala повторно использует те же самые несколько конструкций (например, синтаксис PartialFunction используется как тело блока catch)
  • scala имеет несколько простых правил, которые позволяют создавать код библиотеки (что может выглядеть так, как если бы у языка были специальные ключевые слова/конструкции). Я думаю здесь о неведениях; методы, содержащие двоеточия; допустимые символы идентификатора; эквивалентность X(a, b) и a X b с экстракторами. И так далее
  • scala объявление-сайт. Это означает, что система типа просто выходит из вашего пути. Больше никаких подстановочных знаков и ? super T

Мое личное мнение состоит в том, что этот аргумент полностью и полностью фиктивный. Система типа scala, взятая вместе с implicits, позволяет писать откровенно непроницаемый код для среднего разработчика. Любое предложение иначе просто нелепо, независимо от того, что приведенные выше "показатели" могут заставить вас думать. (Обратите внимание на то, что те, кого я видел, издеваясь над не-сложностью Java на Твиттере и в других местах, оказались uber-умными типами, которые, по-видимому, иногда имели представление о монадах, функторах и стрелах, прежде чем они были не в курсе брюки).

Очевидные аргументы против этого (конечно):

  • Вам не нужно писать такой код
  • вам не нужно подталкивать к среднему разработчику

Из них мне кажется, что справедливо только # 2. Независимо от того, записываете ли вы код достаточно сложным, как scalaz, я думаю, что просто глупо использовать этот язык (и продолжать использовать его) без реального понимания системы типов. Как еще можно извлечь лучшее из языка?

Ответ 5

Миф: методы и функции - одно и то же.

Фактически, функция - это значение (экземпляр одного из классов FunctionN), а метод - нет. Джим МакБит объясняет различия более подробно. Наиболее важными практическими различиями являются:

  • Только методы могут иметь параметры типа
  • Только методы могут принимать неявные аргументы
  • Только методы могут иметь именованные и стандартные параметры
  • При обращении к методу подчеркивание часто необходимо для выделения вызова метода из приложения частичной функции (например, str.length оценивает число, а str.length _ оценивает функцию с нулевым аргументом).

Ответ 6

Существует миф о том, что Scala сложно, потому что Scala - сложный язык.

Это ложь - с помощью множества показателей, Scala не более сложна, чем Java. (Размер грамматики, строки кода или количество классов или количество методов в стандартном API и т.д.)

Но это, несомненно, так, что Scala код может быть свирепо трудно понять. Как это может быть, если Scala не является сложным языком?

Ответ заключается в том, что Scala является мощным языком. В отличие от Java, которая имеет множество специальных конструкций (например, перечислений), которые выполняют одну конкретную вещь, и требует, чтобы вы изучали специализированный синтаксис, применимый только к одной, Scala имеет множество очень общих конструкций. Смешивая и сопоставляя эти конструкции, можно выразить очень сложные идеи с очень маленьким кодом. И, что неудивительно, если кто-то приходит, у кого нет такой же сложной идеи и пытается понять, что вы делаете с этим очень компактным кодом, они могут оказаться сложными - более сложными, даже если они увидели пару страниц кода, чтобы сделать то же самое, с тех пор, по крайней мере, они поймут, сколько концептуального материала нужно было понять!

Существует также проблема, являются ли вещи более сложными, чем они действительно должны быть. Например, некоторые из видов гимнастики, присутствующие в библиотеке коллекций, делают коллекции радостными в использовании, но озадачивают их внедрение или расширение. Цели здесь не особенно сложны (например, подклассы должны возвращать свои собственные типы), но требуемые методы (типы с более высоким уровнем, неявные сборщики и т.д.) Являются сложными. (На самом деле так сложно, что Java просто отказывается и не пытается, а не делает это "правильно", как в Scala. Кроме того, в принципе есть надежда, что это улучшится в будущем, поскольку метод могут развиваться, чтобы более точно соответствовать цели.) В других случаях цели сложны; list.filter(_<5).sorted.grouped(10).flatMap(_.tail.headOption) немного беспорядок, но если вы действительно хотите взять все числа меньше 5, а затем взять каждый второй номер из 10 в оставшемся списке, ну, это просто сложная идея, а код довольно много говорит, что он делает, если вы знаете основные операции с коллекциями.

Резюме: Scala не является сложным, но позволяет компактно выражать сложные идеи. Компактное выражение сложных идей может быть сложным.


Существует миф о том, что Scala не является развертываемым, тогда как широкий спектр сторонних библиотек Java может быть развернут без второй мысли.

В той мере, в которой этот миф существует, я подозреваю, что он существует среди людей, которые не привыкли отделять виртуальную машину и API от языка и компилятора. Если java == javac == Java API в вашем уме, вы можете немного нервничать, если кто-то предлагает использовать scalac вместо javac, потому что вы видите, насколько хорошо работает JVM.

Scala заканчивается как байт-код JVM, а также его собственная пользовательская библиотека. Нет никаких оснований больше беспокоиться о развертывании Scala в небольшом масштабе или как часть какого-либо другого крупного проекта, поскольку при развертывании любой другой библиотеки, которая может или не может оставаться совместимой с какой-либо JVM, вы предпочитаете. Разумеется, команда разработчиков Scala не подкрепляется такой же силой, как коллекции Google, или Apache Commons, но ее по меньшей мере так же сильно позади, как и проект Java Advanced Imaging.

Ответ 7

Некоторые распространенные заблуждения, связанные с библиотекой Актеров:

  • Актеры обрабатывают входящие сообщения параллельно, в нескольких потоках/против пула потоков (фактически, обработка сообщений в нескольких потоках противоречит концепции актеров и может привести к условиям гонок - все сообщения обрабатываются последовательно в одном потоке ( потоковые субъекты используют один поток как для обработки и исполнения почтовых ящиков, так и для участников на основе событий могут использовать один поток VM для выполнения, используя многопоточный исполнитель для планирования обработки почтовых ящиков))
  • Неиспользуемые исключения не изменяют поведение/состояние актера (на самом деле все неперехваченные исключения завершают действие актера)

Ответ 8

Миф:

def foo() = "something"

и

def bar = "something"

то же самое.

Это не так; вы можете вызвать foo(), но bar() пытается вызвать метод apply StringLike без аргументов (приводит к ошибке).

Ответ 9

Миф: вы можете заменить сгиб с уменьшением при вычислении чего-то вроде суммы с нуля.

Это распространенная ошибка/заблуждение среди новых пользователей Scala, особенно тех, которые не имеют опыта предшествующего функционального программирования. Следующие выражения не эквивалентны:

seq.foldLeft(0)(_+_)

seq.reduceLeft(_+_)

Эти два выражения отличаются тем, как они обрабатывают пустую последовательность: сложение дает действительный результат (0), а сокращение вызывает исключение.

Ответ 11

Миф: this.type относится к тому же типу, представленному this.getClass.

В качестве примера этого неправильного представления можно предположить, что в следующем коде тип v.me равен B:

trait A { val me: this.type = this }

class B extends A

val v = new B

В действительности, this.type относится к типу, единственным экземпляром которого является this. В общем случае x.type является одноэлементным типом, единственным экземпляром которого является x. Поэтому в приведенном выше примере тип v.me равен v.type. Следующий сеанс демонстрирует принцип:

scala> val s = "a string"
s: java.lang.String = a string

scala> var v: s.type = s
v: s.type = a string

scala> v = "another string"
<console>:7: error: type mismatch;
 found   : java.lang.String("another string")
 required: s.type
       v = "another string"

Ответ 12

Scala имеет типы ввода и уточнения типов (структурные типы), тогда как Java не делает.

Миф обрушился Джеймсом Ири.

Ответ 13

Миф: Scala обладает высокой степенью масштабируемости, не определяя, какие формы масштабируемости.

Scala действительно может быть очень масштабируемым с точки зрения способности выражать денотационную семантику более высокого уровня, и это делает его очень хорошим языком для экспериментов и даже для масштабирования производства в масштабе уровня проекта top согласованной.

Однако каждый ссылочно непрозрачный язык (т.е. допускает изменчивые структуры данных) является императивным (а не декларативным) и не будет масштабироваться для WAN снизу вверх, несогласованной составности и безопасности. Другими словами, императивные языки - это композиционные (и защитные) спагетти w.r.t. несогласованная разработка модулей. Я понимаю, что такое несогласованное развитие, по-видимому, в настоящее время считается большинством, что это "мечта о трубе" и, возможно, не является первоочередной задачей. И это не должно унижать преимущества композиционности (т.е. Устранять угловые случаи), которые может обеспечить семантическая унификация более высокого уровня, например. модель теории категорий для стандартной библиотеки.

Вероятно, для многих читателей будет значительный когнитивный диссонанс, и они могут преждевременно нажимать "вниз", прежде чем полностью понять вопрос, который я поднимаю, тем более, что есть популярные заблуждения относительно императивного и декларативного (т.е. mutable vs неизменяемый), (и нетерпеливый против ленивого,) например монадическая семантика никогда не является по своей сути императивной но есть ложь, что она есть. Да, в Haskell монада IO является императивной, но для императора не имеет ничего общего с монадой.

Я объяснил это более подробно в разделах "Copute Tutorial" и "Purity", которые находятся либо на домашней странице, либо временно на эта ссылка.

Могу сказать, что я очень благодарен Scala, но я хочу уточнить, что Scala масштабирует, а что нет. Мне нужно Scala для того, что он делает хорошо, то есть для меня это идеальная платформа для прототипа нового декларативного языка, но Scala сама по себе не является исключительно декларативной, а ссылочная прозрачность afaik не может быть реализована компилятором Scala, кроме сохранения возможности использовать val всюду.

Я думаю, мой вопрос относится к дебатам о сложности Scala. Я нашел (до сих пор и в основном концептуально, так как пока ограниченный фактический опыт работы с моим новым языком), который удаляет изменчивость и циклы, сохраняя подтипирование diamond multiple inheritance (который Haskell не имеет), радикально упрощает язык. Например, беллетристика Unit исчезает, а afaics, множество других проблем и конструкций становится ненужным, например. нестандартная теория стандартной библиотеки, для понимания и т.д.