Ранее
В последнем эпизоде мы рассмотрим некоторые изменения в Monyet, The Crystal реализации Monkey.
Моя история со Scala
Я начал использовать Scala более десяти лет назад с версии 2.6. Все было хлипко, поддержки IDE почти не было, но было интересно, ново и весело. Концепции были свежими и сногсшибательными. Потом появились новые версии, и люди подхватили волну; все говорили о новом большом деле. Я катаюсь на волне, как могу. Я сделал хорошо, очень хорошо, на самом деле. Благодаря Scala я мигрировал не один раз, а дважды; Я оставил свою семью и свою страну и отправился в новые приключения за границей. Я очень благодарен Scala.
Но время шло, а гики любят новые блестящие штучки, так что я двинулся на более зеленые пастбища (и продолжаю двигаться). За последние три года я не написал ни строчки кода на Scala профессионально. Много Python, Kotlin, Java (немного TypeScript и Go), но не Scala.
Возвращаемся к Scala 3.
Позвольте представить вам Langur, мою реализацию языка Monkey на Scala 3.
Опыт возвращения в известное место через много лет. Знакомый, но странный.
Что-то я любил, что-то нет, а теперь я могу видеть другие вещи в другом свете благодаря времени, проведенному в других странах.
Хорошие части
Новые перечисления
В Scala была старая версия перечислений, которую на практике никто не использовал, поскольку она была недружелюбной и не имела некоторых функций. Тем не менее, новые перечисления великолепны и обладают всеми функциями, ожидаемыми от современной реализации перечислений.
Расширения
Вдохновленные Kotlin, расширения — отличный способ заменить неявные классы, а также, теоретически, они должны быть быстрее, поскольку они скомпилированы в вызов функции, а не создание экземпляра оболочки + вызов функции.
Скорость компилятора
Он чувствует себя быстрее, или теперь у меня есть лучшая машина. В любом случае
Функции, которые я не использовал, но выглядят великолепно
Given and Using выглядит как правильный способ заменить имплициты. Типы Union и Intersection отлично подходят для других языков, и я надеюсь, что реализация scala также будет образцовой.
Мех части
Новый синтаксис
*Райан Рейнольдс, но почему? мем*
В чем причина? Чтобы привлечь разработчиков Python? Это совсем не похоже на Python. И вы можете смешивать и сочетать оба синтаксиса в одном файле?
Я провел добрых 20 минут, ломая голову над кодом, который не компилировался, когда понял, что случайно нажал табуляцию… и сообщение об ошибке компилятора совсем не помогло.
Метапрограммирование
Радует, что теперь есть стандартный способ делать макросы. Но он настолько сложен, что я избегаю его использования. Мой вариант использования был настолько простым, что я предпочитал копировать и вставлять свой код, а не поддерживать код макроса.
IntelliJ IDEA еще не готова.
С самим языком проблем нет. Лучший способ описать поддержку Scala 3 в IntelliJ — «случайно». Он случайным образом автоматически импортирует, случайным образом автоматически завершает работу, случайным образом перестает работать, случайным образом дает сбой и так далее.
Я также не виню команду плагинов Scala; изменения огромны, и надлежащая поддержка потребует много работы.
Он по-прежнему работоспособен, работает быстро, и меня не заблокировали. Но это не знакомый IntelliJ опыт помощи на этом пути.
Части, которые выглядят по-другому спустя много лет
Сопоставление шаблонов Scala — это потрясающе
Мне удалось написать очень компактный код с сопоставлением с образцом. Kotlin when + smart casts + destructuring — подходящая замена, но заметьте, как хорошая. Например.
По сравнению с:
AnyVal
В Scala 3 нет поддержки байтов без знака, но я создал разумное приближение с помощью AnyVal.
Типы Kotlin Nullable против варианта Scala
Я был большим защитником Scala Option до такой степени, что портировал его на Kotlin под своей старой библиотекой funKTionale.
Уже нет; после многих лет Kotlin типы Option выглядят неуклюжими, многословными и полными церемоний. Вместо этого типы Nullable покрывают 99% реальных вариантов использования, а для оставшегося 1% вы можете использовать Option from Arrow (я предоставил часть исходного кода).
Пытаясь избежать всех этих церемоний, я был осторожен в том, когда Option был нужен. После этого я перенес эти изменения в исходный код Kotlin, что было так же просто, как удалить один символ ?
вместо удаления полной подписи Option[T]
и/или Some(T)/map/foreach/for yield
invocation.
И хотя легко думать, что Nullable Types и Options функционально эквивалентны, они генерируют очень разные байт-коды, что приводит к различиям в производительности/потреблении памяти.
E.g.
Этот код Scala функционально эквивалентен…
Это код Котлина.
Точно такие же строки кода и эквивалентные, но идиоматические на их собственном языке.
Код Scala создает этот байт-код, декомпилированный с помощью декомпилятора Procyon.
Не считая двух дополнительных классов, которые я сюда не включил.
Код Kotlin создает этот байт-код, декомпилированный с помощью Procyon:
Легко, без instanceof
, без кастинга, без оберток, без дополнительных вызовов.
Производительность
Давайте поговорим о производительности. Как всегда, мы запустим традиционный тест Monkey fibonacci(35)
и сравним Мои реализации на Go, Kotlin и Scala, как интерпретированные(eval)
, так и скомпилированные/VM
Интерпретируемый режим
И Kotlin, и Scala быстрее, чем Go, что свидетельствует о том, насколько хорошо JVM выполняет JIT-оптимизацию. Но Kotlin в 1,41 раза быстрее Scala.
Если говорить о потреблении памяти:
Kotlin (с JVM) потребляет 367,76 МБ, а Scala (с JVM) — 617,45 МБ.
Скомпилированный режим/режим виртуальной машины
Неудивительно, что Go быстрее, чем Kotlin и Scala, поскольку работа с байтами — одна из сильных сторон Go. Kotlin в 1,38 раза быстрее Scala.
Если говорить о потреблении памяти.
Kotlin (с JVM) потребляет 362,98 МБ, а Scala (с JVM) — 596,64 МБ.
Я все еще поддерживаю свою теорию о том, что использование Option
влияет на производительность Scala, но на данный момент это просто теория, поскольку я не могу подключить профилировщик VisualVM к коду Scala, чтобы проверить, что происходит.
Заключение
Scala 3 — хороший язык, новые дополнения сделали язык более понятным. Я по-прежнему предпочитаю Kotlin, но у меня не будет проблем с переходом на Scala на профессиональном уровне.