Эта статья, как и мой предыдущий пост, не похожа на то, что обычно публикуют на Хабре. Здесь не объясняется никаких новых или старых концепций, я не рассказываю что такое ООП и функциональное программирование, сложного кода почти нет. Я хочу пригласить вас к дискуссии стоит ли начинать программировать с языка Scala.
Меня иногда просят научить программированию или помочь с поиском подходящего курса. Я хорошо понимаю недостатки и сложности со скалой, но думаю, что Scala 3 — подходящий язык, для того чтобы начать обучение с него, если правильно составить курс. Вся языковая мощь и сложность, конечно, не нужны начинающему программисту, но ему и незачем о них знать. На скале можно писать вполне простой и понятный код, постепенно наращивая инструментарий.
Я согласен с теми комментаторами, кто считает что для этого нужен толковый преподаватель. Это безусловно. Или талантливый преподаватель, который разбирается в предмете, или хорошая книжка, или толковый курс просто необходимы. Иначе есть риск захлебнуться, так и не научившись плавать.
Можно ли выучить Scala без знания Java?
И тем не менее я считаю, что Scala — это язык будущего.
Если коротко, то Scala — это возможность научиться функциональному программированию на безопасном языке, у которого есть большое будущее
Умный компилятор
У скалы один из самых умных и сложных компиляторов. Это приводит к медленным билдам (особенно в первых версиях языка), и за это скалу хейтят. Но зато мы можем отдать компилятору очень много работы по анализу кода, проверке его на безопасность и отсутствие ошибок, что очень важно для программиста. Эта сложность — на стороне разработчика, в том числе и начинающего, которому компилятор очень помогает и облегчает работу.
Скала — это единственный язык, где я пишу код, и он сразу работает без утомительной отладки. Конечно, так происходит не всегда, но с джавой, джаваскриптом, си, паскалем и бейсиком так не происходило никогда. Я люблю говорить, что джава — это язык для компилятора, а скала — это язык для программиста.
JVM-экосистема
Как известно, Джеймс Гослинг, создатель языка джава, считает самой лучшей ее частью джава-машину. Действительно, много инженеров потратило десятки человеко-лет на разработку виртуальной машины и достигли скоростей, в некоторых случаях превышающих Си++. Вот исследование производительности JVM в мобильных устройствах, в нем чаще побеждает нативный код на Си, но в одном случае победила JVM: Java vs C app performance.
Java Memory Model (Модель памяти для многопоточных вычислений) — это зрелая, непротиворечивая, проверенная многими годами промышленного программирования парадигма, которая при правильном использовании гарантирует достаточный уровень абстракции и безопасности. Благодаря этому возможны удобные конструкции для параллельного программирования, доступные даже начинающим.
1. Обзор языка Scala 👍 (Уроки программирования на Scala)
Кроме того, на джаве написаны миллионы строк кода, которые вы можете использовать из скалы или без проблем в нее транслировать.
Кстати, Джеймсу Гослингу скала тоже нравится.
Но в этом всем есть и минусы. Как мы знаем, высокоуровневые абстракции протекают, и для того чтобы программировать на скале, важно знать как устроена виртуальная машина джава, и учитывать ее особенности. Например, такие как Type Erasure. Это довольно серьезный минус, но плюсы от использования JVM его перевешивают.
Эволюция vs революция
В экосистеме скалы приняты довольно слабые гарантии обратной совместимости по сравнению с джавой. С одной стороны, это приводит к тому, что разработчикам постоянно приходится поддерживать свой код в форме при переходе на новую версию языка или библиотек. Кроме того, разработчикам библиотек приходится прибегать к кросс-компиляции для того чтобы обеспечить несколько версий скомпилированных библиотек, подходящих для нескольких версий языка. Это, безусловно, минус.
Но с другой стороны такой подход обеспечивает быстрое и динамичное развитие языка, которое не может себе позволить джава. Именно поэтому я думаю что будущее — за скалой.
К тому же, в Scala 3 появилось типизированное абстрактное синтаксическое дерево компилятора TASTY, которое позволит взаимодействовать классам, собранным разными версиями компилятора. Разумеется, начинающим программистам нет нужды разбираться в этом.
Scala 3
Благодаря более слабым гарантиям обратной совместимости, разработчики языка получили возможность пересмотреть его основы, включая синтаксис.
Первоначальным посылом к созданию скалы было сделать язык промышленного уровня, на котором будет приятно программировать. Это действительно был большой шаг вперед.
Но некоторые решения, принятые более 15 лет назад, были неверными и приводили к неочевидному, либо многословному коду. И сейчас создатели языка делают его действительно лучше. После этих изменений шансы скалы в качестве первого языка программирования заметно вырастают.
Я уже пару лет с нетерпением жду его выхода и мечтаю начать писать на нём. Вот сжатый рассказ Мартина Одерски про новую версию языка: Countdown to Scala 3 by Martin Odersky. Для опытных разработчиков — интересная статья Annoying things in Scala 2 that’ll be (mostly) gone in Scala 3
DOT
Dependent Object Types — это теоретические основы языка Scala 3, разработанные его основателем Мартином Одерски. Мало какой язык может похвастать математически точным исчислением, лежащем в его основе.
Согласитесь, приятно учить язык с таким бэкграундом, хотя начинающим программистам знать о нём не обязательно.
Выразительность и лаконичность
То, что я больше всего люблю в языке — это его сжатость и лаконичность. Я ненавижу длиннейшие конструкции джавы, в которых приходится сложно и многословно объяснять компилятору простые вещи. Моя любимая шутка про джаву — что это такой язык, в котором уан-лайнер занимает около 30 строк. Так вот, в скале уан-лайнер — это уан-лайнер.
Я думаю, что это качество важно не только для опытных разработчиков, но и для тех кто только изучает язык. Думаю, выразительность — это та причина, по которой так популярны динамические и скриптовые языки. Уверен, скала способна с ними в этом поспорить. И даже сама послужить отличным скриптовым языком.
Конечно, лаконичность не должна наносить ущерб читаемости кода. Таких неудачных примеров в программировании полно, вспомним регулярные выражения, паттерн-матчинг и парсер-комбинаторы. Понятно, что для написания библиотек важно понимать сложные концепции и знать много умных слов. Но для того, чтобы ими пользоваться и писать простой код, всего этого знать не надо. Минимальный уровень скалы, который подойдет начинающим, очень простой.
Вот мой любимый пример для библиотечного кода на скале. Конечно, он не предназначен для начинающих разработчиков:
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 $» > 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
В новой версии языка даже есть возможность писать намного меньше фигурных скобок, если есть желание. Это будет выглядеть примерно так:
enum IndentWidth: case Run(ch: Char, n: Int) case Conc(l: IndentWidth, r: Run) def that match case Run(ch2, n2) => n1 this that match case Conc(l2, r2) => l1 == l2 r1 false def < (that: IndentWidth): Boolean = this 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
Статическая типизация
По-моему это самое важное, что должно быть в первом языке программирования. Программисту важно понимать, что не стоит складывать яблоки с апельсинами.
Именно по этой причине на мой взгляд не стоит начинать обучение с Питона, Руби, Джаваскрипта, Си и Си++. Динамическая типизация — это верный способ выстрелить себе в ногу.
Другое дело, что статическая типизация неудобна, неочевидна и требует дополнительного бойлер-плейта. Скала вполне успешно позволяет избавиться от этих недостатков в простых программах.
ООП
Объектно-ориентированное программирование — это самая популярная парадигма, без которой не обходится ни один современный язык программирования.
В скале эта парадигма изначально присуща языку, в отличии от Питона, Си/Си++ и в каком-то смысле джаваскрипта. Разумеется, сейчас у этих языков с ООП полный порядок.
Функциональное программирование
Функциональное программирование — это многообещающая тенденция. Скале она присуща в не меньшей степени чем ООП, и они взаимно обогащают друг друга благодаря этому языку. Рискну предположить, что скала — первый язык промышленного уровня с такими свойствами. Сейчас за ним подтягивается Котлин и другие более новые языки.
Начинающим разработчикам стоит узнать про функциональное программирование подробнее, этот подход позволяет писать гибкий, надежный и хорошо масштабируемый код. Вот несколько хабропостов о нём:
- Почему вы должны думать о функциональном программировании?
- Почему разработчики влюбляются в функциональное программирование?
- Почему функциональное программирование такое сложное?
Иммутабельность
Вообще-то это свойство функционального программирования. Мне кажется очень важным прививать умение пользоваться неизменяемыми структурами данных с самого начала. Это позволит в будущем создавать безопасный многопоточный код. И не только многопоточный.
Расширяемость
Как известно, название языка изначально преподносилось как аббревиатура Scalable Language. Особенности языка позволяют писать гибкие и красивые DSL, удобные даже для не-программистов, вкладывать абстракции друг в друга, создавать очень удобные библиотеки и простые скрипты.
Часто этот инструмент обращается против пользователей библиотек, повышая порог входа в их API. Но в умелых руках такая гибкость может обратиться в большое благо. Опытные разработчики могу создавать на Scala простое и удобное API, тем самым заметно облегчая жизнь начинающим программистам.
Мощь
В целом язык скала предоставляет большое количество мощных инструментов, и обратная сторона этого — высокий порог входа, особенно в отсутствии хорошего курса, учебника, или наставника.
Но думаю, что с хорошим наставником или туториалом вполне можно начинать изучать программирование с языка скала и получать правильные привычки статической типизации, функционального программирования и иммутабельных структур данных.
Рынок вакансий
Конечно, вакансий для скала-программистов значительно меньше, чем для джава-программистов. Но зато Scala выше оплачивается.
Вот вам картинка про области применения скалы:
Мои первые книжки
Самая лучшая книжка про скалу, которую я читал — Scala by Example Мартина Одерски, написанная уже 10 лет назад. Прежде чем начинать сейчас читать книгу по скале, очень рекомендую убедиться что она обновлена до версии Scala 3.
А любимый курс — это Functional Programming in Scala, я проходил его в самой первой версии, с тех пор он, конечно, успел измениться. Первые уроки этого курса основываются все на той же Scala by Example. Сейчас команда курса работает над его обновлением.
Если вы хотите поиграть скалой или дотти, не устанавливая IDE — добро пожаловать в Scastie.
Пример кода
Много примеров короткого кода на скале можно найти вот в этом обсуждении: Samples of Scala and Java code where Scala code looks simpler/has fewer lines? Вот один из них:
Scala
object Main extends App
Java 8
import java.util.*; class Main < public static void main(String[] args) < Listkeywords = Arrays.asList(«Apple», «Ananas», «Mango», «Banana», «Beer»); Map 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) < Listkeywords = Arrays.asList(«Apple», «Ananas», «Mango», «Banana», «Beer»); Map result = new HashMap(); for(String k : keywords) < char firstChar = k.charAt(0); if(!result.containsKey(firstChar)) < result.put(firstChar, new ArrayList()); > result.get(firstChar).add(k); > for(List list : result.values()) < Collections.sort(list); >System.out.println(result); > >
Поступь прогресса
На прощанье — шутка Кея Хорстмана «The March of Progress»
1980: C
printf(«%10.2f», x);
1988: C++
cout
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(«%10.2f», x);
2008: Scala and Groovy
printf(«%10.2f», x)
2012: Scala 2.10
println(f»$x%10.2f»)
На этом я рискну опубликовать этот пост, но по-прежнему планирую его дописывать по результатам обсуждения с вами.
- изучение программирования
- tutorial
- Программирование
- Scala
Источник: habr.com
Язык программирования Scala
Scala — язык программирования, совмещающий объектно-ориентированную и функциональную парадигмы. “Внутри” Скала во многом базируется на синтаксисе и принципах Java. Он даже использует Java Virtual Machine для запуска одного кода на различных платформах.
История языка
Scala разработан в 2003 году сотрудниками политехнического университета Лозанны в Швейцарии. Главной задачей разработчиков было создание языка с максимальной масштабируемостью, то есть способностью справляться с возрастающим уровнем нагрузки при расширении компонентов. Основное внимание уделялось проработке абстрагирования и агрегирования составляющих языка.
В платформе также было решено объединить две парадигмы программирования — функциональную и объектную. Кроме мультипарадигмальности, важной особенностью Scala стала статическая типизация. Предыдущие статичные языки обычно придерживались только одной парадигмы.
Преимущества и недостатки Scala
К плюсам языка можно отнести несколько моментов.
- Кроссплатформенность.
Благодаря использованию JVM код на Скала запускается на любом устройстве, где установлена эта виртуальная машина. В том числе и на “умной технике” — от чайника до холодильника. Программисту при этом не приходится думать о драйверах и других аспектах совместимости. - Продвинутая масштабируемость.
При проектировании системы на Scala ее в любой момент можно расширить или “ужать” за счет абстрактных конструкций. Это упрощает планирование разработки. - Совместимость с Java.
У Scala и Java 100% интегрируемость. Оба языка без труда считывают код друг друга и уживаются в одной программе. Это позволяет строить сложные, многоуровневые системы и дорабатывать уже существующие проекты на Java с применением функционала Scala. - Параллелизм.
В Scala при помощи акторов удобно настраивается параллельное выполнение нескольких операций для ускорения работы программы. Такая модель параллелизма отличается от той, что применяется в большинстве других языков. - Полное погружение в ООП.
Код на Scala чаще всего пишут по объектно-ориентированному принципу. Сама программа на этом языке является одним большим объектом, что уже говорит о многом.
Есть у Scala и свои минусы.
- Усложненность в сравнении с Java.
Языки хоть и похожи, но не идентичны. На освоение Скала понадобиться время, даже при изначальном знании принципов Java. К тому же синтаксис Scala уже не настолько интуитивен и читабелен. - Долгая компиляция.
Сборка программы в исполняемый код на компиляторе Scala происходит довольно медленно. На больших проектах это может значительно замедлять разработку. - Малая популярность.
В распространенности Scala уступает не только своему “прародителю” Java, но и другим языкам. Многие программисты считают, что существующих возможностей привычных платформ вполне хватает для предметной разработки и переход на Scala, со значительно отличающейся архитектурой, не оправдывает себя. Но, как минимум на западе тенденция начинает меняться. Scala в свои продукты внедряют Twitter и другие крупные корпорации.
Основные отличия от Java
В целом код на Scala лаконичнее, чем на Java. При использовании функционального стиля решение задачи на Скала занимает в разы меньше строк. Синтаксис в Scala заметно упрощен — точки запятой в конце строки необязательны, как иногда и фигурные скобки.
Второй важный момент — отсутствие в Java ряда структур, добавленных в Scala. Например, case-классов и поддержки DSL.
Для Java, исключительно из-за его более длительного существования, написано больше фреймворков и в целом доступно больше инструментов разработки. Но Скала со временем также обрастает полезными дополнениями.
Хоть Джава и Скала оба используют байт-код для компиляции программы и ее перевода в машинный код, второй язык справляется с этим немного быстрее. Правда, при работе с сетевыми ресурсами разница становится уже малозначимой.
Основные сферы применения
Скала считается языком программирования общего назначения, и в теории подходит для решения любого рода задач — от создания десктопных программ до написания серверных приложений. При этом чаще всего язык применяется для разработки в веб-среде, особенно когда дело касается объемных, нагруженных проектов вроде социальных сетей, многостраничных информационных порталов и т.п. В этом помогают популярные фреймворки Scala — Lift и Play. Их на своих сайтах задействуют такие новостные гиганты, как BBC и New York Times.
Второе распространенное использование языка — разработка кроссплатформенного ПО. Программировать для большого числа устройств и операционных систем на Скала удобно за счет уже упоминавшейся Java Virtual Machine.
Примеры кода
Простой вывод надписи в консоли на Scala выглядит так.
object HelloWorld extends App
Элементарную функцию по добавлению к переменной определенного числа можно написать в две строки.
def addFive(a: Int) = a + 5 addOne(1)
Результатом выполнения будет 6.
Заключение
Scala во многом представляет из себя улучшенную версию Java с расширенными возможностями для программирования в функциональном стиле. Чаще всего Скала применяется для работы с веб-проектами и для создания кроссплатформенных приложений. Выбрав Scala в качестве основного языка разработки, можно сократить время на реализацию продукта и расширить возможности его применения.
Источник: appfox.ru
Быстрый старт со Scala для начинающих и не очень
Scala – строгий статически типизированный JVM-based язык, успешно совмещающий парадигмы объектно-ориентированного и функционального программирования. В языке есть классы, функции высшего порядка, анонимные функции, обобщенное программирование. Использование Java-кода из Scala не вызывает трудностей, синтаксически языки очень близки. В этой статье мы разберем основные элементы языка, достаточные для того, чтобы начать на нем писать.
Настройка окружения
Scala — язык, работающий на JVM, поэтому для работы требует установленную JDK (минимальная версия 1.6). Ее можно взять отсюда. После установки JDK можно приступить к установке самой Scala. Скачать свежую версию можно на официальном сайте. Последняя версия на момент написания статьи — 2.11.6.
Для того, чтобы все корректно работало из командной строки, рекомендуется прописать переменные среды JAVA_HOME и SCALA_HOME , а также дополнить переменную PATH путями к выполняемым файлам. На Linux и MacOS это делается так:
export JAVA_HOME= export SCALA_HOME= export PATH=$PATH:$JAVA_HOME/bin:$SCALA_HOME/bin
Для того, чтобы сохранить эти настройки, их надо прописать в ~/.bashrc или ~/.bash_profile .
На Windows команда немного другая:
set JAVA_HOME= set SCALA_HOME= set PATH=%PATH%;%JAVA_HOME%bin;%SCALA_HOME%bin
Прописать эти опции постоянно можно в настройках системы: Control Panel → Advanced System Settings → Environmental Variables.
После выполнения всех манипуляций можно проверить результат, запустив:
> java -version java version «1.8.0_31» Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode) > scala -version Scala code runner version 2.11.6 — Copyright 2002-2013, LAMP/EPFL
SBT
Простые скрипты и маленькие программы можно, конечно, компилировать и запускать вручную с помощью команд scalac и scala . Однако, по мере того, как количество файлов будет расти, ручная компиляция будет становиться все более нудной. Вместо этого используют системы сборки. Для сборки кода на Scala можно использовать стандартные для Java (неофициально) maven, gradle или ant, но сообщество и сами разработчики рекомендуют sbt (simple build tool).
Примечание: если вы устанавливаете sbt, то можете пропустить отдельную установку scala, так как система сборки скачает ее автоматически
Описание процесса сборки находится либо в файле build.sbt в корне проекта, либо в файлах .scala в папке project там же. Само описание – это программа на Scala (которая, в свою очередь, может собираться с помощью sbt как отдельный проект, который… ну, вы поняли).
Синтаксис .sbt -файла напоминает синтаксис Scala с некоторыми дополнениями и ограничениями. Минимальный build.sbt выглядит примерно так (пустые строки обязательны):
name := «My Project» version := «0.1.0» scalaVersion := «2.11.6» libraryDependencies ++= Seq( «org.scalatest» %% «scalatest» % «1.6.1» % «test» )
Исходники помещаются в папку src/main/scala и src/test/scala по пути, соответствующем иерархии пакетов (как в Java). Чтобы собрать, протестировать и запустить проект, необходимо в любой поддиректории проекта выполнить следующие команды:
> sbt compile > sbt test > sbt run
или через интерактивную консоль:
> sbt sbt> compile sbt> test sbt> run
Последовательное выполнение команд выглядит немного необычно (обратите внимание на точку с запятой в начале — это особенность синтаксиса):
> sbt sbt> ; compile; test; run
REPL
Отличным помощником в разработке будет REPL (Read-Eval-Print-Loop), или по-другому, интерактивная консоль. Очень удобно проверять в ней небольшие функции, отлаживать код или просто посмотреть возможности языка. Для запуска REPL наберите sbt console в командной строке. Вы увидите примерно следующее:
> sbt console Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0 [info] Set current project to test (in build file:/C:/Users/foxmk/Desktop/test) [info] Starting scala interpreter. [info] Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25). Type in expressions to have them evaluated. Type :help for more information. scala>
Все! Можно писать команды на Scala и сразу же их выполнять:
scala> 1 + 1 res1: Int = 2 scala> def f(x: Int) = x * 2 f: (x: Int)Int scala> f(4) res2: Int = 8 scala> println(«Hello!») Hello! scala>
Для выхода из REPL можно нажать Ctrl+D. Все примеры на Scala далее можно протестировать в REPL, для вставки больших кусков кода можно воспользоваться командой :paste .
IDE
Использование IDE для разработки на Scala не обязательно, однако сильно упрощает процесс. Скала — язык со сложной семантикой, поэтому возможности IDE более ограничены, чем, скажем, при разработке на Java. Тем не менее даже простая подсветка несуществующих методов и автодополнение существующих может сильно облегчить жизнь. Самые популярные IDE для Scala — это IntelliJ IDEA и Eclipse. Для IDEA есть плагин от JetBrains, в случае с Eclipse есть ее вариант Scala IDE.
Переменные, значения и типы.
В Scala переменные и значения объявляются ключевым словом val или var . val — это неизменяемая переменная (значение), аналог final в Java. var — обычная переменная. Например:
> val x = «Some immutable string» > var y = «I CAN CHANGE THIS!» > y = «WHOA! I HAVE CHANGED THIS!» > x = «OOPS!» Error:(3, 4) reassignment to val x = «OOPS!»>;> ^
Аналогичный код на Java будет выглядеть так:
public final String x = «Some immutable string»; public String y = «I CAN CHANGE THIS!»; y = «WHOA! I HAVE CHANGED THIS!»; x = «OOPS!»; // Ошибка компиляции
Здесь мы видим сразу несколько приятных особенностей Scala:
- точка с запятой не обязательна (работает автоматический вывод);
- указания типа переменной необязательно (также работает автоматический вывод типов);
- ключевое слово public подразумевается по умолчанию.
Типы переменных указываются после имени, через двоеточие. Также в Scala нет, как таковых, примитивных типов ( int , float , boolean и т.д.). Их заменяют соответствующие классы Int , Float , Boolean и т.д. Любая переменная — экземпляр какого-либо класса. Иерархия классов начинается с Any , все классы наследуются от него (аналог Object в Java).
val i: Int = 0 // Scala public int i = 0; // Java val flag: Boolean = true // Scala public boolean flag = true; // Java
Применение привычных операторов, при этом, на самом деле — вызов метода: a + b тождественно a.+(b) . Вариант записи без точки применим к любым методам (с некоторыми ограничениями).
Функции, анонимные функции, методы
Функция в Scala объявляется с помощью ключевого слова def . Пример объявления и применения функции:
def addOne(a: Int) = a + 1 addOne(1) // res0: Int = 2
Аналогичный код на Java:
public int addOne(int a)
Как видно на примере, необязательны не только точка с запятой и указание типа, но и фигурные скобки вокруг единственного выражения и слово return . Более того, его использование считается плохой практикой. Из функции возвращается значение последней выполненной команды.
На самом деле, функция — это тоже объект. Каждая функция в Scala — это экземпляр класса Function , у которого есть метод apply . Поэтому мы вполне можем записать так (знак подчеркивания ставится на место аргумента функции):
val functionValue = addOne _ functionValue.apply(1) // res1: Int = 2
Вызов метода apply подразумевается по умолчанию, поэтому использование функций внешне выглядит как в Java:
functionValue(1) // res2: Int = 2
Все четыре вызова функции идентичны. Представление функций в виде объектов позволяет оперировать с ними, как с остальными объектами: передавать в качестве аргументов, возвращать из других функций, расширять дополнительными методами и т.д., что позволяет Scala полноценно поддерживать парадигму функционального программирования.
Конечно, присутствуют анонимные функции (лямбда-функции). Они объявляются так:
val f = (x: Int) => x + 1 f(1) // res3: Int = 2
Здесь мы объявляем анонимную функцию, которая принимает один целочисленный аргумент и присвоил ее переменной f , после чего применяем f как обычную функцию.
Классы и объекты
Если вы программировали на Java, многие вещи, касающиеся объектно-ориентированного программирования будут вам знакомы. Класс объявляется ключевым словом class , новый экземпляр — через new . Методы класса — это функции, объявленные в его теле. Поля класса указываются сразу после имени, как список аргументов.
При этом, по умолчанию они объявляются как private val . То есть, если мы не укажем никаких модификаторов, указанное поле будет доступно только внутри класса и будет неизменяемым. Класс можно сделать абстрактным, добавив abstract перед объявлением. Основное отличие от Java здесь заключается в отсутствии конструктора. Код, который должен выполняться при создании объекта, пишется прямо в теле класса. Как при этом реализовать несколько конструкторов с различным числом аргументов, мы рассмотрим позже. Пример использования класса:
И аналогичный код на Java:
class Foo < private int x_; Foo(int x) < _x = x; >public int bar(int y) < return x + y; >> Foo foo = new Foo(1) int result = foo.bar(1) // result теперь равен 2
Как видим, public указывать не обязательно, аргументы конструктора доступны во всем классе, локальное приватное поле создавать также не обязательно.
Кроме того, в Scala мы можем объявить сразу объект, без создания класса, с помощью ключевого слова object . Таким образом реализуется паттерн «Одиночка» (Singleton).
object Singleton(field: String) < def squareMe(x: Int) = x*x >Singleton.squareMe(2) // res5: Int = 4
Аналог на Java будет куда более многословен.
public class Singleton < private static Singleton instance = null; protected Singleton() < // Exists only to defeat instantiation. >public static Singleton getInstance() < if(instance == null) < instance = new Singleton(); >return instance; > public int squareMe(int x) < return x*x; >> int a = Singleton.getInstance().squareMe(2) // a теперь равен 4
В этом примере мы пометили конструктор как protected , чтобы исключить возможность его вызова извне, обращение к объекту будет осуществляться через метод getInstance() , который при первом своем вызове инициализирует экземпляр класс, а при последующих возвращает уже созданный экземпляр. Кроме того, вполне допустимо существование объекта и класса с одним и тем же именем, при этом они делят область видимости. Поэтому необходимость в директиве static отпадает — методы, объявленные не в классе, а в объекте ведут себя как статические. Такой объект называется в терминологии Scala «companion object» («объект-компаньон»).
Вернемся к конструкторам. Вспомним, что при применении любого объекта к некоторым аргументам по умолчанию вызывается метод apply . Этим мы и воспользуемся и напишем класс с несколькими конструкторами, статическими методами, изменяемыми и неизменяемыми полями в идиоматичном для Scala стиле и продублируем этот же код на Java.
HTTP Archive подвёл итоги веба за 2020 год
object MyUselessClass < def staticMethod(x: Int) = x + 5 def apply(immutableField: Int): MyUselessClass = new MyUselessClass(immutableField, 2) def apply(immutableField: Int, mutableField: Int): MyUselessClass = new MyUselessClass(immutableField, mutableField) def apply(immutableField: Int, mutableField: Int, privateField: Int): MyUselessClass = new MyUselessClass(immutableField, mutableField, privateField) >class MyUselessClass(val immutableField: Int, var mutableField: Int, privateField: Int = 8 /*значние по умолчанию*/) < def instanceMethod() = < val sumOfFields = immutableField + mutableField + privateField MyUselessClass.staticMethod(sumOfFields) >> // Первый конструктор, обратите внимание на отсутствие ‘new’, // так как это на самом деле вызов метода ‘apply’ val myUselessObject = MyUselessClass(1) // аналогично предыдущему варианту val myAnotherUselessObject = MyUselessClass.apply(1) // Третий конструктор val myThirdUselessObject = MyUselessClass(1, 2, 3) // Вызов метода myUselessObject.instanceMethod() // res6: Int = 16 // Поля доступны также, как методы myUselessObject.mutableField // res7: Int = 2 myUselessObject.immutableField // res8: Int = 1 myUselessObject.mutableField = 9 myUselessObject.mutableField // res9: Int = 9 // Вызов статического метода MyUselessClass.staticMethod(3) // res10: Int = 8
public class MyUselessClass < private int immutableField_; private int mutableField_; private int privateField_ = 8; MyUselessClass(int immutableField) < immutableField_ = immutableField; mutableField_ = 2; >MyUselessClass(int immutableField, int mutableField) < immutableField_ = immutableField; mutableField_ = mutableField; >MyUselessClass(int immutableField, int immutableField, int privateField) < immutableField_ = immutableField; mutableField_ = mutableField; privateField_ = privateField; >int getImmutableField() < return immutableField; >int getMutableField() < return mutableField; >void setMutableField(int newValue) < mutableField = newValue; >public static int staticMethod(int x) < return x + 5; >public int instanceMethod() < int sumOfFields = immutableField + mutableField + privateField; return staticMethod(sumOfFields); >> // Первый конструктор MyUselessClass myUselessObject = new MyUselessClass(1) // Третий конструктор MyUselessClass myAnotherUselessObject = new MyUselessClass(1, 2, 3) // Вызов метода myUselessObject.instanceMethod() // вернет 16 // Поля доступны также, как методы myUselessObject.getMutableField // вернет 2 myUselessObject.getImmutableField // вернет 1 myUselessObject.setMutableField(9) myUselessObject.getMmutableField // вернет 9 // Вызов статического метода MyUselessClass.staticMethod(3) // вернет 8
Интерфейсы и трейты
Аналогом Java-интерфейса в Scala является трейт (trait). Как ни удивительно, объявляется он с помощью ключевого слова trait . Как и интерфейсы Java, трейты содержат только объявления методов и допускают множественное наследование. В отличие от интерфейса, в трейте можно описывать поля класса и частично реализовывать методы. Наследование как трейтов, так и абстрактных классов осуществляется с помощью extend (первый родитель) и with (последующие родители). Пример использования:
trait FirstTrait < def foo(x: Int) >trait SecondTrait < def bar(y: Int) = y + 5 >class ComplexClass extends FirstTrait with SecondTrait
Ключевое слово override необязательно, но его использование является хорошей практикой.
Другие особенности и отличия от Java
Как и в Java, в Scala классы, трейты и функции можно параметризовать. Параметры типов пишутся в квадратных скобках после имени класса или функции. Так определяется интерфейс Foo , который принимает некоторый тип A и содержит метод bar ? который принимает значение типа A и некоторого типа B и возвращает объект типа C . Конкретные типы A , B и C будут определены в реализации интерфейса.
trait Foo[A] < def bar[B, C](a: A, b: B): C // метод, который принимает аргументы типа A и B и возвращает тип C >
Конструкция if / else всегда возвращает значение выражения, которое стоит последним ввыполняемом блоке. Скобки вокруг условия обязательны, скобки вокруг тела, в котором только одна инструкция, можно опустить.
val a = if (true == false) < // true-branch >else < // false-branch >
Блок try / catch / finally выглядит в Scala так:
try < // some code >catch < case e: SomeException =>. case e: SomeOtherException => . > finally < // some code >
Циклы while ничем не отличаются от варианта в Java:
var i = 1000 while (i > 0)
А циклы for — наоборот, совсем не похожи (о них мы подробнее поговорим в следующей статье):
val numbers = 1 to 1000 for (number
Также вы, возможно, могли заметить литерал . . Он имеет тип Nothing который является подкласс любого класса. При вызове . кидает исключение NotImplemented . Это примерно аналог undefined в Python. . можно ставить в качестве заглушки вместо тела функции, к написанию которого вы планируете вернуться позже.
Заключение
Итак, мы установили и настроили среду разработки для Scala, посмотрели основные элементы языка, сходства с Java и отличия от нее. Этого вполне должно хватить для того, чтобы начать писать простой и рабочий код. В следующей статье мы подробнее рассмотрим элементы функционального программирования, case-классы, pattern-matching и другие высокоуровневые особенности языка.
Источник: tproger.ru