Scala как первый язык / Хабр

Scala как первый язык / Хабр Сертификаты

Вводные статьи по scala

Данные статьи представляют собой краткие обзоры языка (15-20 страниц). Носят скорее идеологический/исторический характер — как сам автор (Одерский) видит свое детище, что он считает самым важным/отличительным/характерным.

Основные статьи по scala

Данные статьи освещают и проясняют основные характеристики языка.

  • «Scalable Component Abstractions», Odersky …. We identify three programming language abstractions for the construction of reusable components: abstract type members, explicit selftypes and modular mixin composition. Together, these abstractions enable us to transform an arbitrary assembly of static program parts with hard references between them into a system of reusable components.… We demonstrate this approach in two case studies, a subject/observer framework and a compiler front-end.
  • «Type classes as objects and implicits», Odersky …, Type classes were originally developed in Haskell as a disciplined alternative to ad-hoc polymorphism. Type classes have been shown to provide a type-safe solution to important challenges in software engineering and programming languages such as, for example, retroactive extension of programs. They are also recognized as a good mechanism for concept-based generic programming and, more recently, have evolved into a mechanism for type-level computation. This paper presents a lightweight approach to type classes in object-oriented (OO) languages with generics using the CONCEPT pattern and implicits (a type-directed implicit parameter passing mechanism).
  • «Matching Objects With Patterns», Odersky …, Pattern Matching во всей красе с Case classes / Extractors сравнение с более классическими решениями (Visitor, Type-Test/Type-Cast, …)

Jvm-экосистема

Как известно, Джеймс Гослинг, создатель языка джава, считает самой лучшей ее частью джава-машину. Действительно, много инженеров потратило десятки человеко-лет на разработку виртуальной машины и достигли скоростей, в некоторых случаях превышающих Си .

На Android 6 AArch64 JVM победила Си в математических вычислениях, хотя и проиграла во всех других видах
На Android 6 AArch64 JVM победила Си в математических вычислениях, хотя и проиграла во всех других видах

Java Memory Model (Модель памяти для многопоточных вычислений) — это зрелая, непротиворечивая, проверенная многими годами промышленного программирования парадигма, которая при правильном использовании гарантирует достаточный уровень абстракции и безопасности. Благодаря этому возможны удобные конструкции для параллельного программирования, доступные даже начинающим.

Кроме того, на джаве написаны миллионы строк кода, которые вы можете использовать из скалы или без проблем в нее транслировать.

Кстати, Джеймсу Гослингу скала тоже нравится.

Но в этом всем есть и минусы. Как мы знаем, высокоуровневые абстракции протекают, и для того чтобы программировать на скале, важно знать как устроена виртуальная машина джава, и учитывать ее особенности. Например, такие как Type Erasure. Это довольно серьезный минус, но плюсы от использования JVM его перевешивают.

Scala 3

Благодаря более слабым гарантиям обратной совместимости, разработчики языка получили возможность пересмотреть его основы, включая синтаксис.

Первоначальным посылом к созданию скалы было сделать язык промышленного уровня, на котором будет приятно программировать. Это действительно был большой шаг вперед.

Но некоторые решения, принятые более 15 лет назад, были неверными и приводили к неочевидному, либо многословному коду. И сейчас создатели языка делают его действительно лучше. После этих изменений шансы скалы в качестве первого языка программирования заметно вырастают.

Я уже пару лет с нетерпением жду его выхода и мечтаю начать писать на нём. Вот сжатый рассказ Мартина Одерски про новую версию языка: Countdown to Scala 3 by Martin Odersky. Для опытных разработчиков — интересная статья Annoying things in Scala 2 that’ll be (mostly) gone in Scala 3

Выразительность и лаконичность

То, что я больше всего люблю в языке — это его сжатость и лаконичность. Я ненавижу длиннейшие конструкции джавы, в которых приходится сложно и многословно объяснять компилятору простые вещи. Моя любимая шутка про джаву — что это такой язык, в котором уан-лайнер занимает около 30 строк. Так вот, в скале уан-лайнер — это уан-лайнер.

Я думаю, что это качество важно не только для опытных разработчиков, но и для тех кто только изучает язык. Думаю, выразительность — это та причина, по которой так популярны динамические и скриптовые языки. Уверен, скала способна с ними в этом поспорить. И даже сама послужить отличным скриптовым языком.

Конечно, лаконичность не должна наносить ущерб читаемости кода. Таких неудачных примеров в программировании полно, вспомним регулярные выражения, паттерн-матчинг и парсер-комбинаторы. Понятно, что для написания библиотек важно понимать сложные концепции и знать много умных слов.

Про сертификаты:  АЦСК Украина |ProKey

Вот мой любимый пример для библиотечного кода на скале. Конечно, он не предназначен для начинающих разработчиков:

class Stack[ A] {

  def push[B >: A](elem: B): Stack[B] = new Stack[B] {
    override def top: B = elem
    override def pop: Stack[B] = Stack.this
    override def toString = s"$elem ${Stack.this}"
  }

  def top: A = sys.error("no element on stack")
  def pop: Stack[A] = sys.error("no element on stack")
  override def toString = ""
}

object VariancesTest extends App {
  println(Stack().push("hello").push(Object()).push(7))
}

В новой версии языка даже есть возможность писать намного меньше фигурных скобок, если есть желание. Это будет выглядеть примерно так:

enum IndentWidth:
  case Run(ch: Char, n: Int)
  case Conc(l: IndentWidth, r: Run)

  def <= (that: IndentWidth): Boolean = this match
    case Run(ch1, n1) =>
      that match
        case Run(ch2, n2) => n1 <= n2 && (ch1 == ch2 || n1 == 0)
        case Conc(l, r)   => this <= l
    case Conc(l1, r1) =>
      that match
        case Conc(l2, r2) => l1 == l2 && r1 <= r2
        case _            => false

  def < (that: IndentWidth): Boolean =
    this <= that && !(that <= this)

  override def toString: String = this match
    case Run(ch, n) =>
      val kind = ch match
        case ' '  => "space"
        case 't' => "tab"
        case _    => s"'$ch'-character"
      val suffix = if n == 1 then "" else "s"
      s"$n $kind$suffix"
    case Conc(l, r) =>
      s"$l, $r"

object IndentWidth:
  private inline val MaxCached = 40

  private val spaces = IArray.tabulate(MaxCached   1)(new Run(' ', _))
  private val tabs = IArray.tabulate(MaxCached   1)(new Run('t', _))

  def Run(ch: Char, n: Int): Run =
    if n <= MaxCached && ch == ' ' then
      spaces(n)
    else if n <= MaxCached && ch == 't' then
      tabs(n)
    else
      new Run(ch, n)
  end Run

  val Zero = Run(' ', 0)
end IndentWidth

Иммутабельность

Вообще-то это свойство функционального программирования. Мне кажется очень важным прививать умение пользоваться неизменяемыми структурами данных с самого начала. Это позволит в будущем создавать безопасный многопоточный код. И не только многопоточный.

Книги

На рынке присутствует большое количество книг (порядка 20) по Scala, но мне в наибольшей степени понравились следующие 4

Курсы/подборки по scala

Охват материала на небольшую книгу, но не книги. От «классиков».


Да,

Материалы: akka

Akka

— de facto стандарт framework-а для многопоточных и распределенных архитектур на основе акторов для JVM.

Материалы: finagle

Finagle

Материалы: functional programming in scala

— сильная книга от одного из контрибюторов в Scalaz.

Материалы: metaprogramming / macroses

A particularly interesting aspect of macros is that they are based on the same API used also for Scala’s runtime reflection, provided in package scala.reflect.api. This enables the sharing of generic code between macros and implementations that utilize runtime reflection.

Our flavor of macros is reminiscent of Lisp macros, adapted to incorporate type safety and rich syntax. Unlike infamous C/C preprocessor macros, Scala macros: 1) are written in full-fledged Scala, 2) work with expression trees, not with raw strings, 3) cannot change syntax of Scala. [here]

Macros are functions that are called by the compiler during compilation. Within these functions the programmer has access to compiler APIs. For example, it is possible to generate, analyze and typecheck code. You can learn more about macros from documentation. [here]

Def macros are shipped as an experimental feature of Scala since version 2.10.0. A subset of def macros, pending a thorough specification, is tentatively scheduled to become stable in one of the future versions of Scala.

Материалы: metaprogramming / reflection

A particularly interesting aspect of macros is that they are based on the same API used also for Scala’s runtime reflection, provided in package scala.reflect.api. This enables the sharing of generic code between macros and implementations that utilize runtime reflection.

Until 2.10, Scala has not had any reflection capabilities of its own. Instead, one could use part of the Java reflection API, namely that dealing with providing the ability to dynamically inspect classes and objects and access their members. However, many Scala-specific elements are unrecoverable under standalone Java reflection, which only exposes Java elements (no functions, no traits) and types (no existential, higher-kinded, path-dependent and abstract types).

In Scala 2.10, a new reflection library was introduced not only to address the shortcomings of Java’s runtime reflection on Scala-specific and generic types, but to also add a more powerful toolkit of general reflective capabilities to Scala.… with full-featured runtime reflection for Scala types and generics…

  • «scala-lang.org: Reflection: Overview» Miller, Burmako, Haller
  • «scala-lang.org: Reflection: Environment, Universes, and Mirrors» Miller, Burmako, Haller
  • «scala-lang.org: Reflection: Symbols, Trees, and Types» Miller, Burmako, Haller
  • «scala-lang.org: Reflection: Annotations, Names, Scopes, and More» Miller, Burmako, Haller
  • «scala-lang.org: Reflection: TypeTags and Manifests» Miller, Burmako, Haller

Материалы: netty

Netty

— an asynchronious and event-driven network application framework for rapid development of maintanable high performance protocol servers and clients. Netty — это de fakto стандарт для использования java.net.*, NIO и NIO.2 (Akka и Finagle используют «под капотом» Netty, Zookeeper напрямую NIO/NIO.2). Хотя можно и напрямую реализовывать шаблоны асинхронной обработки сообщений

Про сертификаты:  Экзамен на Гражданство РФ 2021 - Прохождение экзамена, ответы

Материалы: parser combinators

В Scala включен пакет (scala.util.parsing), который предоставляет инструменты для описания грамматики External DSL на Scala в формате близком к EBNF. Т.е. это «внутренний DSL» для создания «внешних DSL».

In Scala, parsers are implemented as monads — hence defining combinators for parsers are just monadic transformations implementing sequencing, alternation or any other composition operations.

В ряде предметных областей можно строить API в виде неких примитивных элементов (в данном случае парсеров) и способов комбинирования этих элементов определенным образом (комбинаторы). В данном случае в самом ядре языка есть все необходимое для построение внешних DSL.

  • «Parser Combinators in Scala», Odersky …, — в статье постепенно пишется своя библиотека Parser Combinators и сравнивается с scala.util.parsing. Строятся парсеры для simple arithmetic expressions, xml, lambda calculus that tracks variable binding
  • «Combinator Parsing, Chapter 31 of Programming in Scala, First Edition» — базовый учебник от Martin Odersky, Lex Spoon, and Bill Venners. Строятся парсеры для arithmetic expressions, json,. Есть второе издание, но оно не доступно в свободном доступе.
  • «Monadic Parser Combinators», Hutton Meijer
    — одна из статей, на которую опирался Одерский с товарищами при проектировании parser combinators для Scala
  • «How to replace failure by a list of successes: A method for exception handling, backtracking, and pattern matching in lazy functional languages, Wadler
  • »Higher-order functions for parsing”, Hutton
  • «Functional parsers», Fokker
  • «Deterministic, Error-Correcting Combinator Parsers», Swierstra Duponcheel
  • «Parsec: Direct Style Monadic Parser Combinators: For The Real World»
  • «Packrat Parsing: Simple, Powerful, Lazy, Linear Time»
  • «Monadic Parsing in Haskell»
  • «Pickler Combinators (functional Pearl)» — pickler-ами в Haskell называют «сериализаторы», специализированные функции для преобразования объектов в памяти в байтовые массивы. Предлагается построение picкler-ом для сложных структур данных получать как комбинации pickler-ов для базовых типов. This pearl was practically motivated: an SML version of the pickler library is used inside the SML.NET compiler. The essential new ingredient of pickler combinators is the tying together of the pickling and unpickling actions in a single value.
  • «Instant Pickles: Generating Object-Oriented Pickler Combinators for Fast and Extensible Serialization» Miller, Haller, Burmako, Odersky — аналогичный подход (предыдущей статье) для Scala
  • «Even Higher-Order Functions for Parsing or Why Would Anyone Ever Want To Use a Sixth-Order Function? (functional pearl)», Chris Okasaki — парсер — это функция первого порядка, которая принимает входные данные, а возвращает результат разбора к каком-то формате. Комбинаторы парсеров — это функции второго порядка, которые принимают функции первого порядка (парсеры) и возвращают функции первого порядка (парсеры). Крис Окасаки смог найти разумную функцию шестого порядка!!! связанную с парсерами.

Материалы: zookeeper

Zookeeper

— fail-safe централизованный сервис для управления конфигурационной информацией, именованием, распределенной синхронизации и других групповых сервисов, составная часть

Материалы: использование fp в финансовой отрасли

По ряду причин (возможность описания предметной области на языке комбинаторов) функциональные языки программирования любят использовать в финансовой отрасли, что создает спрос на «функциональщиков» в Нью-Йорке и Лондоне.

Мои первые книжки

Самая лучшая книжка про скалу, которую я читал — Scala by Example Мартина Одерски, написанная уже 10 лет назад. Прежде чем начинать сейчас читать книгу по скале, очень рекомендую убедиться что она обновлена до версии  Scala 3.

А любимый курс — это Functional Programming in Scala, я проходил его в самой первой версии, с тех пор он, конечно, успел измениться. Первые уроки этого курса основываются все на той же Scala by Example. Сейчас команда курса работает над его обновлением.

Если вы хотите поиграть скалой или дотти, не устанавливая IDE — добро пожаловать в Scastie.

Поступь прогресса

На прощанье — шутка Кея Хорстмана «The March of Progress»

1980: C 

printf(".2f", x);

1988: C

cout << setw(10) << setprecision(2) << fixed << x;

1996: Java

java.text.NumberFormat formatter = java.text.NumberFormat.getNumberInstance(); 
formatter.setMinimumFractionDigits(2); 
formatter.setMaximumFractionDigits(2); 
String s = formatter.format(x); 
for (int i = s.length(); i < 10; i  ) System.out.print(' '); 
System.out.print(s);

2004: Java

System.out.printf(".2f", x);

2008: Scala and Groovy

printf(".2f", x)

2021: Scala 2.10

println(f"$x.2f")

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

Пример кода

Много примеров короткого кода на скале можно найти вот в этом обсуждении: Samples of Scala and Java code where Scala code looks simpler/has fewer lines? Вот один из них:

Scala

object Main extends App {
  val keywords = List("Apple", "Ananas", "Mango", "Banana", "Beer")
  val result = keywords.sorted.groupBy(_.head)
  println(result)
}

Java 8

import java.util.*;

class Main {
  public static void main(String[] args) {
    List<String> keywords = Arrays.asList("Apple", "Ananas", "Mango", "Banana", "Beer"); 
    Map<Character, List<String>> result = keywords.stream().sorted().collect(Collectors.groupingBy(it -> it.charAt(0)));
    System.out.println(result);
  }
}

Java 7

import java.util.*;

class Main {
  public static void main(String[] args) {
    List<String> keywords = Arrays.asList("Apple", "Ananas", "Mango", "Banana", "Beer"); 
    Map<Character, List<String>> result = new HashMap<Character, List<String>>(); 
    for(String k : keywords) {   
      char firstChar = k.charAt(0);     
      if(!result.containsKey(firstChar)) {     
        result.put(firstChar, new  ArrayList<String>());   
      }     
      result.get(firstChar).add(k); 
    } 
    for(List<String> list : result.values()) {   
      Collections.sort(list); 
    }
    System.out.println(result); 
  }
}

Расширяемость

Как известно, название языка изначально преподносилось как аббревиатура Scalable Language. Особенности языка позволяют писать гибкие и красивые DSL, удобные даже для не-программистов, вкладывать абстракции друг в друга, создавать очень удобные библиотеки и простые скрипты.

Про сертификаты:  Власти Петербурга предостерегли горожан от покупки билетов на «Алые паруса» | Новости | Известия | 23.06.2021

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

Рынок вакансий

Конечно, вакансий для скала-программистов значительно меньше, чем для джава-программистов. Но зато Scala выше оплачивается.

Сертификаты экологичности и другие на продукцию skalla

Скала-р управление сертификат на техническую поддержку лицензии системы серверной виртуализации на 1 год, расширенная редакция. 1 cpu – пакет «24×7» — купить лицензию скала-р, цена в ростове-на-дону на официальном сайте

Программно-определяемый инфраструктурный комплекс СКАЛА-Р – готовое решение для создания горизонтально масштабируемойи отказоустойчивой среды виртуализации на платформе типовых серверных х86-узлов.

СКАЛА-Р соответствует требованиям документов «РД НДВ (4)» и технических условий руководящих документов ФСТЭК и может использоваться:

  • В государственных информационных системах вплоть до 1 класса и информационных системах персональных данных вплоть до 1 уровня защищенности.
  • В системах, где к актуальным отнесены угрозы 1-го и 2-го типа (связанные с наличием недокументированных возможностей в системном и прикладном программном обеспечении).

Все программные продукты СКАЛА-Р зарегистрированы в Едином реестре российских программ для электронных вычислительных машин и баз данных Минкомсвязи. Программно-аппаратные комплексы могут быть собраны на базе аппаратного обеспечения, обладающего Заключением Минпромторга РФ о подтверждении производства промышленной продукции на территории Российской Федерации.

✅ Купите СКАЛА-Р Управление Сертификат на техническую поддержку лицензии системы серверной виртуализации на 1 год, Расширенная редакция. 1 CPU – пакет «24×7» на официальном сайте

✅ Лицензия СКАЛА-Р Управление Сертификат на техническую поддержку лицензии системы серверной виртуализации на 1 год, Расширенная редакция. 1 CPU – пакет «24×7» по выгодной цене

✅ СКАЛА-Р Управление Сертификат на техническую поддержку лицензии системы серверной виртуализации на 1 год, Расширенная редакция. 1 CPU – пакет «24×7», лицензионное программное обеспечение купите в Ростове-на-Дону и других городах России

Предлагаем также:

Статическая типизация

По-моему это самое важное, что должно быть в первом языке программирования. Программисту важно понимать, что не стоит складывать яблоки с апельсинами.

Именно по этой причине на мой взгляд не стоит начинать обучение с Питона, Руби, Джаваскрипта, Си и Си . Динамическая типизация — это верный способ выстрелить себе в ногу.

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

Умный компилятор

У скалы один из самых умных и сложных компиляторов. Это приводит к медленным билдам (особенно в первых версиях языка), и за это скалу хейтят. Но зато мы можем отдать компилятору очень много работы по анализу кода, проверке его на безопасность и отсутствие ошибок, что очень важно для программиста. Эта сложность — на стороне разработчика, в том числе и начинающего, которому компилятор очень помогает и облегчает работу.

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

Функциональное программирование

Функциональное программирование — это многообещающая тенденция. Скале она присуща в не меньшей степени чем ООП, и они взаимно обогащают друг друга благодаря этому языку. Рискну предположить, что скала — первый язык промышленного уровня с такими свойствами. Сейчас за ним подтягивается Котлин и другие более новые языки.

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

Эволюция vs революция

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

Но с другой стороны такой подход обеспечивает быстрое и динамичное развитие языка, которое не может себе позволить джава. Именно поэтому я думаю что будущее — за скалой.

К тому же, в Scala 3 появилось типизированное абстрактное синтаксическое дерево компилятора TASTY, которое позволит взаимодействовать классам, собранным разными версиями компилятора. Разумеется, начинающим программистам нет нужды разбираться в этом.

Оцените статью
Мой сертификат
Добавить комментарий