Scala с чего начать
Зачем нужен Scala?
Разбираем, почему это не самый популярный язык.
Встречали в вакансиях позицию разработчика на Scala? Это редкий зверь, но платят нормально. Разберёмся, что это такое и зачем нужно.
Разработчик языка рассчитывал, что Scala станет преемником Java: он наследует многое хорошее из Java, работает по схожим принципам и добавляет что-то своё. И хотя Scala не стал таким же распространённым, всё равно стоит понять, из чего он сделан.
Плюсы Scala
Scala, как и Java, работает под JVM — виртуальной машиной Java (Java Virtual Machine). JVM — это такая прослойка между программой и железом. Благодаря этой прослойке один и тот же код можно исполнить на чём угодно, для чего есть JVM: и на компьютере, и на терминале оплаты, и на умном холодильнике. Не нужно каждый раз думать: «А какие там драйверы экрана?» или «С какой скоростью работает сетевой шлюз?» — всё это берёт на себя JVM, а мы пишем только логику и интерфейс.
Минусы Scala
Но если всё было бы так просто, про Java все давно бы забыли, но этого не произошло. Более того, сейчас не так много Scala-вакансий на рынке, чтобы говорить о популярности этого языка. На это есть несколько причин:
Синтаксис
С точки зрения кода в Scala всё то же самое, что и в Java-языках, кроме некоторых ООП-особенностей, поэтому начнём с привычных деталей, а потом перейдём к отличиям.
Основы. Каждая команда заканчивается точкой с запятой, а присваивание и математические операторы такие же, как в Java и JavaScript.
Типов данных — много, как в любом типизированном языке. Как и в Ruby, каждый тип — это объект, который можно менять, добавлять в него новые методы.
Переменные. Объявляются с помощью служебных слов val и var, но разница между ними в Scala настолько размытая и непрозрачная, что иногда даже опытным разработчикам сложно понять, какое слово будет уместнее в каждой ситуации.
Условные операторы и циклы. Всё привычно — for, while и do-while, но с одним отличием: в цикле for применяется упрощённая запись для организации переменной цикла. Обратите внимание на код ниже — сколько танцев с бубном ради одного цикла, который сам занимает три строки (не считая комментария):
Кто и для чего использует Scala
У Scala нет явно выраженной области применения, как у некоторых других языков. С другой стороны, из-за объединения ООП и функционального программирования этот язык прижился в тех командах, которым нужно совмещать в работе оба подхода.
Второе преимущество — возможность запустить код в любом JVM-окружении, поэтому Scala выбирают те, кому нравится объектный подход, но не нравится то, как это сделано в Java.
Основные популярные фреймворки — Play и Lift, и их используют в основном СМИ и новостные сайты:
С чего начать
Если хотите изучить основы Scala и попробовать свои силы в объектно-ориентированном программировании в мире Java, то вот с чего можно начать.
Большая статья в RSDN Magazine — «Обзор языка программирования Scala». Хороший и понятный материал, но подан в сухом академическом стиле.
«Scala в примерах» в Викиучебнике — написано попроще, но без введения для новичков.
«Руководство по Scala» в Записках задумчивого программиста — просто, понятно, но иногда автор не даёт подробных объяснений тому, что происходит в коде.
Быстрый старт со Scala для начинающих и не очень
Авторизуйтесь
Быстрый старт со Scala для начинающих и не очень
Scala – строгий статически типизированный JVM-based язык, успешно совмещающий парадигмы объектно-ориентированного и функционального программирования. В языке есть классы, функции высшего порядка, анонимные функции, обобщенное программирование. Использование Java-кода из Scala не вызывает трудностей, синтаксически языки очень близки. В этой статье мы разберем основные элементы языка, достаточные для того, чтобы начать на нем писать.
Настройка окружения
Scala — язык, работающий на JVM, поэтому для работы требует установленную JDK (минимальная версия 1.6). Ее можно взять отсюда. После установки JDK можно приступить к установке самой Scala. Скачать свежую версию можно на официальном сайте. Последняя версия на момент написания статьи — 2.11.6.
Для того, чтобы сохранить эти настройки, их надо прописать в
На Windows команда немного другая:
Прописать эти опции постоянно можно в настройках системы: Control Panel → Advanced System Settings → Environmental Variables.
После выполнения всех манипуляций можно проверить результат, запустив:
Примечание: если вы устанавливаете sbt, то можете пропустить отдельную установку scala, так как система сборки скачает ее автоматически
Исходники помещаются в папку src/main/scala и src/test/scala по пути, соответствующем иерархии пакетов (как в Java). Чтобы собрать, протестировать и запустить проект, необходимо в любой поддиректории проекта выполнить следующие команды:
или через интерактивную консоль:
Последовательное выполнение команд выглядит немного необычно (обратите внимание на точку с запятой в начале — это особенность синтаксиса):
Отличным помощником в разработке будет REPL (Read-Eval-Print-Loop), или по-другому, интерактивная консоль. Очень удобно проверять в ней небольшие функции, отлаживать код или просто посмотреть возможности языка. Для запуска REPL наберите sbt console в командной строке. Вы увидите примерно следующее:
Все! Можно писать команды на Scala и сразу же их выполнять:
Использование IDE для разработки на Scala не обязательно, однако сильно упрощает процесс. Скала — язык со сложной семантикой, поэтому возможности IDE более ограничены, чем, скажем, при разработке на Java. Тем не менее даже простая подсветка несуществующих методов и автодополнение существующих может сильно облегчить жизнь. Самые популярные IDE для Scala — это IntelliJ IDEA и Eclipse. Для IDEA есть плагин от JetBrains, в случае с Eclipse есть ее вариант Scala IDE.
Переменные, значения и типы.
Аналогичный код на Java будет выглядеть так:
Здесь мы видим сразу несколько приятных особенностей Scala:
Функции, анонимные функции, методы
Аналогичный код на Java:
Вызов метода apply подразумевается по умолчанию, поэтому использование функций внешне выглядит как в Java:
Все четыре вызова функции идентичны. Представление функций в виде объектов позволяет оперировать с ними, как с остальными объектами: передавать в качестве аргументов, возвращать из других функций, расширять дополнительными методами и т.д., что позволяет Scala полноценно поддерживать парадигму функционального программирования.
Конечно, присутствуют анонимные функции (лямбда-функции). Они объявляются так:
Классы и объекты
И аналогичный код на Java:
Как видим, public указывать не обязательно, аргументы конструктора доступны во всем классе, локальное приватное поле создавать также не обязательно.
Аналог на Java будет куда более многословен.
Интерфейсы и трейты
Ключевое слово override необязательно, но его использование является хорошей практикой.
Другие особенности и отличия от Java
Конструкция if / else всегда возвращает значение выражения, которое стоит последним ввыполняемом блоке. Скобки вокруг условия обязательны, скобки вокруг тела, в котором только одна инструкция, можно опустить.
Блок try / catch / finally выглядит в Scala так:
Циклы while ничем не отличаются от варианта в Java:
А циклы for — наоборот, совсем не похожи (о них мы подробнее поговорим в следующей статье):
Заключение
Итак, мы установили и настроили среду разработки для Scala, посмотрели основные элементы языка, сходства с Java и отличия от нее. Этого вполне должно хватить для того, чтобы начать писать простой и рабочий код. В следующей статье мы подробнее рассмотрим элементы функционального программирования, case-классы, pattern-matching и другие высокоуровневые особенности языка.
Scala Tutorial — Изучите Scala с помощью пошагового руководства
темы:
Особенности Scala
У Scala есть много причин быть популярными и востребованными. Немногие из причин упомянуты ниже:
Область применения
Начало работы с Scala
Scala — это очень совместимый язык, поэтому его можно очень легко установить в операционные системы Windows и Unix.
Так как Scala очень похож на другие широко используемые языки синтаксически, в Scala проще кодировать и изучать. Scala-программы могут быть написаны в любом текстовом редакторе, таком как блокнот, notepad ++ или что-либо в этом роде. Можно также использовать онлайновую IDE для написания кодов Scala или даже установить ее в своей системе, чтобы сделать эти коды более удобными для написания, потому что IDE предоставляют множество функций, таких как интуитивно понятный редактор кода, отладчик, компилятор и т. Д.
Для начала, написание кодов Scala и выполнение различных интригующих и полезных операций, необходимо установить Scala в своей системе. Это можно сделать, следуя пошаговым инструкциям, приведенным ниже:
Мы получим вывод, как показано ниже:
Вывод команды.
Как запустить программу Scala?
Давайте рассмотрим простую программу Hello World.
// Scala программа для печати Hello World
def main(args : Array[String])
// печатает Привет, гики!
println( «Hello, World!» )
Выход:
Как правило, есть два способа запуска программы Scala:
Основы Scala
переменные
Переменные — это просто место хранения. Каждая переменная известна по своему имени и хранит некоторую известную и неизвестную часть информации, известную как значение. В Scala есть два типа переменных:
Пример:
операторы
Оператор — это символ, который представляет операцию, которая должна быть выполнена с одним или несколькими операндами. Операторы позволяют нам выполнять различные виды операций над операндами. В Scala используются следующие типы операторов:
Пример :
// Scala программа для демонстрации
// Операторы
12 хороших курсов по Scala для тех, кто уже что-то знает
Язык программирования Scala громко заявил о себе в 2010-е годы. Сейчас ажиотаж вокруг него спал, но забывать о Scala точно не стоит. Это один из самых популярных коммерческих языков, который используют Twitter, LinkedIn, WhatsApp. Scala-разработчики, возможно, не так востребованы как их коллеги, пишущие на Python или Java, но хороший специалист будет цениться высоко, а знание языка станет безусловным плюсом в резюме. В помощь тем, кто хочет пополнить ряды адептов Scala, Digitaldefynd составил (а мы дополнили) подборку онлайн-курсов и тренингов разных уровней сложности.
Язык программирования Scala громко заявил о себе в 2010-е годы. Сейчас ажиотаж вокруг него спал, но забывать о Scala точно не стоит. Это один из самых популярных коммерческих языков, который используют Twitter, LinkedIn, WhatsApp. Scala-разработчики, возможно, не так востребованы как их коллеги, пишущие на Python или Java, но хороший специалист будет цениться высоко, а знание языка станет безусловным плюсом в резюме. В помощь тем, кто хочет пополнить ряды адептов Scala, Digitaldefynd составил (а мы дополнили) подборку онлайн-курсов и тренингов разных уровней сложности.
Содержание
spoiler#handleClick»>Примечание редакции
Стоимость указана на момент подготовки материала и носит ориентировочный характер.
Актуальные скидки и промокоды некоторых онлайн-площадок можно найти по ссылке.
Apache Spark на Scala для работы с большими данными (Udemy)
Курс разработан для того, чтобы помочь изучить Apache Spark, известную технологию в области BigData. Вы узнаете, как извлекать смысл из массивных наборов данных в отказоустойчивом кластере Hadoop. Освоите искусство формулирования проблем анализа данных при помощи многочисленных практических примеров и научитесь масштабировать их для выполнения в службах облачных вычислений.
Преимущества курса
spoiler#handleClick»>Отзыв
«Это превосходный курс по Spark и Scala. Я никогда не видел ничего подобного среди онлайн-курсов. Я рекомендую его всем, кто хочет иметь ясное понимание концепций Spark. Спасибо за прекрасный курс».
Продолжительность: 9 часов.
Рейтинг: 4.5 из 5.
Scala и Spark для работы с большими данными и машинного обучения (Udemy)
Работа со Spark и Scala — востребованный навык в ИТ-индустрии. Эта сертификация начинается с краш-курса по Scala и дает обзор экосистемы больших данных и Spark. В ней есть множество возможностей получить практический опыт работы с Mlib, платформой для аналитики больших данных Databricks и другими инструментами. После завершения сертификации вы сможете с уверенностью добавить полученные навыки в резюме.
Преимущества курса
spoiler#handleClick»>Отзыв
«Я приобретал другие курсы Jose и раньше. Я познакомился с введением в Scala и Spark на разных ресурсах, включая курсы Udemy, и хотел получить более структурированный материал. Репутация Jose как преподавателя, который объясняет все шаг за шагом, дала мне уверенность, чтобы записаться на этот курс. Мне нравится, что он объясняет „Почему“, а не просто фокусируется на том „Как“. Этот курс наконец-то связал для меня все воедино».
Продолжительность: 10 часов.
Рейтинг: 4.4 из 5.
Scala и функциональное программирование для начинающих (Udemy)
Если у вас есть опыт программирования на любом языке и вам хочется добавить в список своих скилов еще и работу на Scala, то можете обратить внимание на этот курс. Всего 15 часов лекций и, по словам инструктора, вы сможете понимать код Scala в производственных средах и проектах с открытым исходным кодом, научитесь с нуля создавать приложения на этом языке и получите навыки, которые позволят вам работать с такими инструментами, как Spark, Akka и Play.
Преимущества курса
Продолжительность: 15.5 часов.
Рейтинг: 4.6 из 5.
Принципы функционального программирования в Scala (Coursera)
В этой комплексной программе вы изучите элементы стиля функционального программирования и научитесь использовать их для решения ваших повседневных задач. Начнете с создания прочной основы для рассуждений о функциональных программах, прежде чем перейти к доказательству инвариантов и символическому отслеживанию выполнения. Если у вас есть опыт программирования на Java, C#, C, C++, Python, Javascript или Ruby (от одного года), то вы более чем готовы к обучению на этой сертификации.
Преимущества курса
spoiler#handleClick»>Отзыв
«По-настоящему хорошее объяснение инструктора. Хорошие задания. Они дают четкое представление о функциональном программировании. Мне понравилось, как проблемы были разделены на более мелкие».
Продолжительность: 23 часа, по 5 часов в неделю.
Рейтинг: 4.8 из 5.
Scala и функциональное программирование: продвинуты уровень (Udemy)
Курс создан для разработчиков, знакомых со Scala, которые хотели бы усовершенствовать свои знания и навыки. Для того, чтобы пройти данную программу, обязательно иметь хорошее понимание этого языка и функционального программирования. На курсе отобраны и рассмотрены самые важные идеи Scala, продвинутые концепции деконструируются на критические части, а вся теория поддержана демонстрацией реального кода. Полученный на программе опыт поможет продвинуться в разработке сложных масштабируемых систем, настройке существующих инструментов и создании своих собственных.
Преимущества курса
Продолжительность: 14 часов.
Рейтинг: 4.8 из 5.
Специализация по функциональному программированию на Scala (Coursera)
Эта специализация разработана для практического знакомства с популярным языком Scala, а также функциональным программированием. Занятия начинаются с изучения базового блока функциональных парадигм и их использования для решения небольших проблем, а затем переходят к объединению концепций и более крупным задачам. Вы узнаете, как эта парадигма упрощает параллельное и распределенное программирование. К концу обучения вы сможете эффективно применять новые знания в соответствующих проектах.
Преимущества курса
Продолжительность: 5 месяцев, по 5 часов в неделю.
Рейтинг: 4.7 из 5.
Обработка больших данных при помощи Spark Streaming и Scala: практикум (Udemy)
На этом курсе вы получите навыки практической работы с данными Twitter в реальном времени, смоделированными потоками журналов доступа Apache и даже данными, которые используются для обучения моделей машинного обучения. Узнаете, как написать и запустить реальные потоковые задания Spark и завершите обучение, перенося их в кластер Hadoop и запуская в производственной среде.
Преимущества курса
spoiler#handleClick»>Отзыв
«Фантастическая структура, предупреждения компилятора, которые могут сбить с толку кого угодно при запуске кода, и побудили меня создать готовый работающий пакет Spark Streaming за 20 минут. С нетерпением жду того, чтобы проверить код и разобраться с оптимизациями и другими источниками потоковой передачи».
Продолжительность: 6 часов.
Рейтинг: 4.4 из 5.
Анализ больших данных со Scala и Spark (Coursera)
Этот курс покажет вам, как парадигма параллельных данных может быть распространена на распределенный случай с помощью Spark. Изучите модель программирования Spark и поймите, чем она отличается от других, знакомых вам. Получите практический опыт и выясните, когда стоит учитывать вопросы, связанные с распределением, и как они могут сделать работу более эффективной. К концу занятий вы будете в состоянии читать данные из постоянного хранилища, управлять ими, выражать алгоритмы в функциональном стиле.
Преимущества курса
Продолжительность: 28 часов.
Рейтинг: 4.7 из 5.
Scala для начинающих (Udemy)
Данная программа подойдет всем, кто хочет получить комплексное представление об языке программирования Scala и изучить его с нуля. Курс представляет сбалансированное и подробное введение в Scala и его концепции, включая библиотеки Actors и Collections. Если верить преподавателю, то к концу обучения, при условии выполнения всех заданий, вы будете иметь прочные теоретические знания и практические навыки, которые позволят вам уверенно программировать на Scala и использовать все необходимые для этого инструменты.
Преимущества курса
Продолжительность: 5.5 часов.
Рейтинг: 4.7 из 5.
Программирование на Scala (Artima)
Если вы интересуетесь программированием на Scala, но не знаете, с чего начать, то это — подходящий вариант. Разработанное иначе, чем большинство курсов, это руководство рассматривает темы шаг за шагом и отлично подойдет студентам, которые предпочитают учиться по книгам. Кроме основных тем, в нем также рассказывается, как работать с XML, модульным программированием и программированием с графическим интерфейсом, равенством объектов и многое другое. Этот курс со множеством примеров и кодов — фаворит пользователей.
Преимущества курса
Продолжительность: определяете сами.
Рейтинг: 4.4 из 5.
Стоимость: бесплатно.
Apache Spark 3: программирование Spark на Scala для начинающих (Udemy)
Этот курс был разработан, чтобы помочь всем желающим разобраться с программированием Spark и начать применять полученные знания для создания решений по инженерии данных. Вы начнете обучение со знакомства с архитектурой Spark и его фундаментальными концепциями, а затем перейдете к более специфическим темам. Курс основан на рассмотрении конкретных примеров и «живом» кодировании, поэтому все необходимые концепции в нем объясняются по ходу. Для студентов, которые хотят пройти эту программу, обязательно знакомство со Scala.
Преимущества курса
Продолжительность: 7 часов.
Рейтинг: 4.6 из 5.
Проекты с консультациями по программированию на Scala (Coursera)
Новый формат обучения от Coursera — проекты с консультациями — позволяет в сжатые сроки (до 2-х часов) получить полезные навыки, например, изучить основы Scala, разработав мини-игру или объектно-ориентированное программирование на этом языке, практикуясь в написании кода. Обучение проходит в режиме разделенного экрана под руководством преподавателя, который дает вам пошаговые инструкции. Проекты лучше всего подойдут студентам, хотя бы немного знакомым со Scala, а также любым другим языком программирования. Обратите внимание: данный формат недоступен для мобильных устройств и в режиме бесплатного прослушивания.
Преимущества курса
Продолжительность: 1.5 — 2 часа.
Хотите сообщить важную новость? Пишите в Телеграм-бот.
А также подписывайтесь на наш Телеграм-канал.
Первые шаги в Scala
Авторы: Билл Веннерс
Мартин Одерски
Лекс Спун
Перевод: Купаев Михаил
Чистяков Влад
Источник: First Steps to Scala
Материал предоставил: RSDN Magazine #2-2007
Опубликовано: 30.07.2007
Исправлено: 15.04.2009
Версия текста: 1.0
Скала разрабатывается с 2003 группой Мартина Одерского (Martin Odersky) в EPFL, в Лозанне, Швейцария. Он участвовал в создании первой версии generic-ов Java и был автором текущего компилятора javac. Работа над Scala мотивировалась желанием обойти ограничения, накладываемые требованиями обратной совместимости с Java. Так что Scala – это не расширение Java, но она сохраняет возможность взаимодействия с Java.
Одна из причин, способных заставить вас обратиться к программированию на Scala, состоит в том, что Scala позволяет увеличить производительность разработчика по сравнению с Java, сохраняя скорость исполнения JVM, существующие инвестиции в Java-код, знания и множество API, имеющихся для JVM. Scala обладает краткостью языков типа Ruby или Python, но при этом статически типизирована, как и Java. Еще одна причина в том, что Scala поставляется с Erlang-подобной библиотекой Actors, которая существенно упрощает параллельное программирование, но работает под JVM.
По-итальянски Scala означает «лестница». В данной статье мы проведем вас по 12 ступеням, которые помогут вам набраться знаний в Scala. Лучше всего использовать эту статью, проверяя каждый пример с помощью интерпретатора или компилятора Scala. Шаг 1 объясняет, как скачать и установить дистрибутив Scala.
Шаг 1. Скачиваем и устанавливаем Scala
Для исполнения примеров из этой статьи, вам нужно скачать Scala со страницы http://www.scala-lang.org/downloads/index.html. Примеры этой статьи написаны для Scala 2.5.0-RC1, так что вам нужно скачать более свежую версию, чем 2.5.0-RC1. После скачивания архива создайте каталог (возможно, с именем scala), и распакуйте архив в этот пустой каталог. Среди создаваемых при распаковке подкаталогов будет каталог bin с исполняемыми файлами Scala, включая компилятор и интерпретатор. Для удобства использования Scala добавьте путь к каталогу bin в переменную среды PATH. Единственное дополнительное требование – установить Java 1.4 или выше, скачать Java можно с http://java.sun.com/. Можно также использовать Scala через модули расширения Eclipse и IntelliJ, но здесь мы будем считать, что вы используете дистрибутив Scala со scala-lang.org.
Шаг 2. Учимся использовать интерпретатор Scala
Самый простой путь начать работать со Scala – использование интерпретатора Scala, интерактивной оболочки для написания программ и выражений Scala. Просто введите выражение в интерпретаторе, и он вычислит его значение и выведет результат. Интерактивная оболочка Scala называется просто scala. Используется она так:
Если вы напишете выражение и нажмете на ввод:
Эта строка включает:
В последних строках может использоваться идентификатор unnamedX. Например, если до этого unnamed0 был установлен в 3, unnamed0 * 3 будет равно 9:
Чтобы вывести необходимое, но не достаточное приветствие Hello, world!, введите:
Тип результата здесь – scala.Unit, Scala-аналог void в Java. Главная разница между Unit в Scala и void в Java состоит в том, что Scala позволяет записать значение типа Unit, а именно (), а в Java нет значений типа void. (другими словами, как 1, 2 и 3 являются потенциальными значениями типа int в Scala и Java, так () является единственным значением типа Unit в Scala.) За этим исключением Unit и void эквивалентны. В частности, каждый возвращающий void метод в Java отображается на возвращающий Unit метод в Scala.
Шаг 3. Определим некоторые значения и переменные.
Scala различает значения, которые назначаются один раз и никогда не изменяются, и переменные, которые могут изменяться. Значения определяются с помощью ключевого слова val, а переменные – с помощью ключевого слова var. Вот определение значения:
Здесь вводится msg как имя для значения «Hello world!». Тип приведенного выше значения – java.lang.String, поскольку строки Scala – это также и строки Java (на самом деле все Java-классы доступны в Scala).
Этот пример также показывает важную и очень полезную возможность Scala: наследование типов. Заметьте, что в определении значения ничего не говорилось ни о java.lang.String, ни о просто String. Интерпретатор Scala вывел тип значения который будет ему назначен при инициализации. Поскольку msg было инициализировано значением «Hello, world!», и поскольку тип «Hello, world!» – java.lang.String, компилятор присваивает msg тип java.lang.String.
Если интерпретатор (или компилятор) может вывести тип, лучше позволить ему сделать это, чем забивать код ненужными явными указаниями типов. Вы можете, однако, указать тип явно, если хотите. (Например, вы можете захотеть явно указать типы public-членов классов в целях документирования.) В противоположность Java, где вы указываете тип переменной перед ее именем, в Scala тип переменной или значения указывается после имени, отделенный двоеточием. Например:
Или, поскольку java.lang видны со своими простыми именами в Scala-программах, просто:
Возвращаясь к нашему исходному msg, теперь оно определено, и вы можете использовать значение msg:
Что вы не можете сделать с msg, поскольку это значение, а не переменная – переназначить его. Например, посмотрите, как интерпретатор отреагирует на следующее:
Если вам требуется переназначение, вам придется использовать переменную, как в:
Поскольку greeting – это переменная (определенная через var), а не значение (определенное через val), вы можете изменить ее значение позже. Если у вас испортится настроение, например, вы можете изменить greeting на:
Шаг 4. Определим несколько методов
Теперь, поработав с переменными и значениями Scala, вы, возможно, захотите написать метод-другой. Вот как это делается в Scala:
Определения методов начинаются не с val или var, а с def. За именем метода, в данном случае max, идет список параметров в круглых скобках. За каждым параметром метода должно следовать указание типа, предваряемое двоеточием, как принято в Scala, так как компилятор Scala (и интерпретатор тоже, но для простоты дальше будем называть их обоих компилятором) не выводит типы параметров методов. В данном примере метод max принимает два параметра, x и y, оба типа int. За закрывающей скобкой списка параметров метода max вы найдете еще одно указание типа “: Int”. Оно показывает тип возвращаемого значеия метода max.
Иногда компилятор Scala потребует от вас указать возвращаемый тип метода. Если метод рекурсивен, например, вы должны явно указать возвращаемый тип метода. В случае max вы можете опустить указание возвращаемого типа, компилятор выведет его. Таким образом, метод max можно записать как:
Заметьте, что вы должны всегда явно указывать типы параметров метода, независимо от того, будете ли вы явно указывать его возвращаемый тип.
Имя, список параметров и возвращаемый тип, если он указан, образуют сигнатуру метода. Вслед за сигнатурой метода идет знак равенства, а за ним – тело метода. Поскольку тело метода max состоит всего из одного выражения, его необязательно помещать в фигурные скобки, но если хотите – можно. Так что можно написать так:
Если вы собираетесь поместить в тело метода несколько выражений, их нужно заключать в фигурные скобки.
Определив метод, его можно вызвать по имени:
Заметьте, что если метод не принимает параметров, как в:
его можно вызывать как со скобками, так и без них:
Рекомендации по стилю для вызова метода состоят в том, что если метод может иметь побочные эффекты (говорят, что метод имеет побочный эффект, если он изменяет состояние за пределами метода), скобки нужно указывать независимо от того, требует ли их компилятор. В данном случае, поскольку метод greet производит стандартный вывод, у него есть побочные эффекты и его нужно вызывать со скобками, чтобы предупредить программистов, которые будут читать код.
Шаг 5: Пишем скрипты на Scala
Несмотря на то, что Scala предназначена для разработчиков, пишущих большие системы, она замечательно масштабируется вниз, так что вполне естественно использовать ее для создания скриптов. Скрипт – это просто последовательность выражений в файле, которые будут исполняться последовательно (кстати, если у вас все еще работает интерпретатор Scala, можете закрыть его командой :quit). Поместите в файл hello.scala следующее:
Вы получите еще одно приветствие:
Аргументы командной строки для Scala-скрипта вводятся через Scala-массив args. В Scala, как и в Java, нумерация индексов массива начинается с нуля, но к элементу надо обращаться, указывая индекс в круглых, а не в квадратных скобках. Поэтому первый элемент в Scala-массиве steps – это steps(0), а не steps[0]. Чтобы попробовать, напишите следующее в новом файле helloarg.scala:
В этой команде «planet» передается как аргумент командной строки, к которому скрипт обращается как к args(0). То есть вы увидите:
Заметьте также, что этот скрипт содержит комментарий. Как и в Java, компилятор Scala игнорирует символы от // до конца строки, а также любые символы между /* и */. Этот пример также показывает конкатенацию строк с помощью оператора +. Все это работает так, как и ожидалось. Выражение «Hello, » + «world!» выдаст строку «Hello, world!».
Кстати, под Unix можно исполнять Scala-скрипты как скрипты оболочки, если разместить в начале файла директиву, как в следующем файле helloarg:
#!/bin/sh должна быть самой первой строкой файла. После задания разрешения на исполнение:
вы сможете запускать Scala-скрипты как скрипты оболочки, просто сказав:
Шаг 6. Конструкции while и if
Циклы while в Scala пишутся примерно так же, как в Java. Попробуйте использовать while, введя в файл printargs.scala следующее:
Этот скрипт начинается с определения переменной var i = 0. Выведение типов присвоит i тип Scala.Int, поскольку это тип ее исходного значения, 0. Конструкция while на следующей строке приводит к повторению исполнения блока кода в фигурных скобках до тех пор, пока булево выражение i
Рисунок 1. Синтаксис анонимной функции в Scala.
К этому моменту вы можете задаться вопросом, что случилось с теми надёжными циклами, которые вы привыкли использовать в императивных языках типа Java. Чтобы вести программиста в функциональном направлении, в Scala доступен только функциональный родственник императивного for (называемый for comprehension). В этой статье вы не увидите их во всем блеске, но кое-что мы вам покажем. В новом файле forprintargs.scala напишите следующее:
Еще одна очень полезная упорядоченная коллекция – это кортежи, tuple. Как и List, кортежи неизменяемы, но в отличие от List, кортежи могут содержать элементы разных типов. То есть если список может быть List[Int] или List[String], кортеж может содержать и Int, и String одновременно. Кортежи очень полезны, например, если нужно возвращать из метода несколько объектов. Если в Java вы часто создаете JavaBean-подобные классы для хранения нескольких возвращаемых значений, то в Scala вы можете возвратить кортеж. И это просто: чтобы создать новый кортеж для хранения нескольких объектов, просто заключите объекты в скобки, разделив их запятыми. Создав экземпляр кортежа, вы можете обращаться к его элементам индивидуально через точку, подчеркивание и начинающийся с единицы индекс элемента. Посмотрите, например, на код для файла luftballons.scala:
В первой строке этого кода вы создаете новый кортеж, который содержит Int со значением 99 в качестве первого элемента, и String со значением «Luftballons» в качестве второго элемента. Scala выводит тип кортежа как Tuple2[Int, String], и дает этот тип также переменной pair. Во второй строке происходит обращение к полю _1, что даст первый элемент, 99. Точка во второй строке – это та же точка, которая используется при обращении к полю или вызове метода. В данном случае вы обращаетесь к полю _1. Если запустить это скрипт, вы увидите:
Шаг 10. Используем Set и Map
Поскольку Scala должна помочь вам использовать как функциональный, так и императивный стили, в ее библиотеке коллекций делается упор на различение изменяемых и неизменяемых классов коллекций. Например, Array всегда изменяемы, а List всегда неизменны. Когда дело доходит до Set и Map, также предоставляет изменяемые и неизменяемые альтернативы, но другим путем. Для Set и Map Scala моделирует изменяемость в иерархии классов.
Например, Scala API содержит базовый trait для Set, где trait похож на Java-интерфейс (подробнее об этом будет сказано на шаге 12). Scala предоставляет два суб-trait-а, один для изменяемых Set, другой – для неизменяемых. Как можно увидеть на рисунке 2, все три trait-а разделяют одно простое имя Set. Их полностью квалифицированные имена, конечно, различаются, поскольку все они находятся в разных пакетах. Конкретные классы Set в Scala API, такие как показанные на рисунке 2 классы HashSet, расширяют изменяемые либо неизменяемые trait-ы Set (там где в Java вы реализуете интерфейсы, в Scala вы «расширяете» trait-ы). Так что если вам захочется использовать HashSet, вы можете выбирать между изменяемым и неизменяемым вариантами, в зависимости от потребностей.
Рисунок 2. Иерархия классов для Set в Scala.
Чтобы испытать Set в Scala, наберите следующий код в файле jetset.scala:
Первая строка jetSet.scala импортирует изменяемый HashSet. Как и в Java, импорт позволяет использовать в исходном коде простое имя класса, HashSet. После пустой строки, в третьей строке создается новый HashSet, содержащий только элементы типа String, и хранящий результирующую ссылку в jetSet. Заметьте, что как и в случае List и Array, при создании Set его нужно параметризовать типом (в данном случае String), так как все объекты в Set должны иметь один тип. Две следующие строки добавляют три объекта в изменяемый Set с помощью метода +=. Как и большинство других символов, похожих на операторы в Scala, на самом деле это метод, определенный в классе HashSet. Если бы вам захотелось, вместо jetSet += «Lear», можно было написать jetSet.+=(«Lear»). Поскольку метод += принимает переменное число аргументов, ему можно одновременно передать несколько объектов. Например, jetSet += «Lear» добавляет в HashSet один элемент типа String, а jetSet += («Boeing», «Airbus») – два. Наконец, последняя строка выводит, содержит ли Set конкретную строку (как и ожидалось, она выводит false).
Еще один полезный класс коллекций в Scala – Map. Как и в случае Set, Scala предоставляет изменяемую и неизменяемую версии Map, используя иерархию классов. Как показано на рисунке 3, иерархия классов для Map очень похожа на иерархию для Set. Есть базовый trait Map в пакете scala.collection, и два суб- trait-а Map: изменяемый Map в scala.collection.mutable и неизменяемый – в scala.collection.immutable.
Рисунок 3. Иерархия классов для Map в Scala.
Реализации Map, такие как HashMap, показанные в иерархии классов на рисунке 3, реализуют изменяемый или неизменяемый trait. Чтобы увидеть Map в действии, создайте файл treasure.scala со следующим кодом.
Поскольку map – это очень полезная конструкция в программировании, Scala предоставляет для Map фабричный метод, по духу похожий на фабричный метод, показанный в шаге 9 и позволяющий создавать List без ключевого слова new. Чтобы попробовать в действии этот краткий способ создания map, создайте файл numerals.scala со следующим кодом:
В numerals.scala вы используете тот факт, что trait неизменяемого Map автоматически импортируется в любой исходный код Scala. То есть когда вы пишете Map в первой строке кода, интерпретатор Scala знает, что вы имеете в виду scala.collection.immutable.Map. В этой строке вы вызываете фабричный метод объекта-синглтона неизменяемого Map, передавая ему пять кортежей ключ/значение в качестве параметров. Этот фабричный метод возвращает экземпляр неизменяемого HashMap, содержащий переданные пары ключ/значение. Имя фабричного метода – apply, но, как упомянуто в шаге 8, если написать Map(. ), это будет трансформировано компилятором в Map.apply(. ). Если вы выполните скрипт numerals.scala, он выведет IV.
Шаг 11. Понимание классов и синглтон-объектов
До сих пор вы писали Scala-скрипты, чтобы понять концепции, представленные в этой статье. Но везде, кроме простейших проектов, вы, скорее всего, захотите разбить код приложения на классы. Чтобы попробовать, создайте файл greetSimply.scala со следующим кодом:
На самом деле greetSimply.scala – это Scala-скрипт, но он содержит определение класса. Однако этот первый пример показывает, что в Scala, как и в Java, классы инкапсулируют поля и методы. Поля определяются с помощью val или var. Methods определяются через def. Например, в классе SimpleGreeter, greeting – это поле, а greet – это метод. Для использования этого класса вы создаете новый экземпляр с new SimpleGreeter, и помещаете ссылку на этот экземпляр в значение g. Затем вы вызываете экземплярный метод greet для g. При запуске этого скрипта вы будете потрясены видом очередного Hello, world!.
Хотя классы в Scala во многом похожи на Java, в некоторых отношениях они силно различаются. Одно из различий между Java и Scala касается конструкторов. В Java у классов есть конструкторы, которые могут принимать параметры, тогда как в Scala классы могут принимать параметры напрямую. Нотация Scala короче – параметры классов могут использоваться напрямую в теле классов, не нужно определять поля и писать присвоения, копирующие параметры конструктора в поля. Это может дать существенную экономию, особенно в маленьких классах. Чтобы увидеть это в действии, введите следующий код в файл greetFancily.scala:
Вместо определения конструктора, принимающего String, как это делается в Java, в greetFancily.scala, вы помещаете параметр greeting этого конструктора в скобках сразу за именем самого класса, перед открытием фигурных скобок тела класса FancyGreeter. При определении таким способом greeting в сущности становится значением (не переменной – его нельзя переназначить) поля, доступным везде в теле класса. Реально вы передаете его println в теле метода greet. Если вы запустите этот скрипт командой scala greetFancily.scala, вы получите воодушевляющее:
Это здорово и кратко, но что, если вы захотите проверять строку, переданную первичному конструктору FancyGreeter, на null, и генерировать NullPointerException? К счастью, это возможно. Любой код, находящийся внутри блока кода класса верхнего уровня (фигурные скобки, окружающие само определение класса) и не являющийся частью определения метода, компилируется в тело первичного конструктора. В сущности, первичный конструктор будет добавлять final-поле для каждого параметра конструктора (в круглых скобках, следующих за названием класса). Например, чтобы проверить передаваемый параметр на null, создайте класс greetCarefully.scala со следующим кодом:
В greetCarefully.scala выражение if находится в середине тела класса, что в Java не скомпилировалось бы. Компилятор Scala помещает это if в тело первичного конструктора, сразу после кода, инициализирующего поля. То есть если вы передаете внутрь в первичном конструкторе null, как в последней строке скрипта greetCarefully.scala, первичный конструктор сперва проинициализирует значением null поле greeting. Затем он будет исполнять выражение if, проверяющих равенство null поля greeting, и поскольку так оно и есть, выдаст NullPointerException. Если запустить greetCarefully.scala, вы увидите исключение NullPointerException.
В Java вы иногда задаете классам несколько конструкторов с перегруженными списками параметров. это возможно и в Scala, однако вы должны назначить один из их первичным конструктором, и поместить параметры этого конструктора непосредственно за именем класса. Затем вы помещаете любые дополнительные конструкторы в тело класса как методы this. Вот демонстрирующий это код, который надо поместить в файл greetRepeatedly.scala:
Первичный конструктор RepeatGreeter принимает не только строковый параметр greeting, но и целочисленный счетчик числа раз выводов приветствия. Однако RepeatGreeter содержит и определение второго конструктора, метода this, принимающего один строковый параметр greeting. Тело этого конструктора состоит из единственного выражения: вызова первичного конструктора, параметризованного переданным greeting и значением счетчика 1. Последние четыре строки скрипта greetRepeatedly.scala создают два экземпляра RepeatGreeter, по одному для каждого конструктора, и вызывают у каждого greet. Если запустить greetRepeatedly.scala, он выведет:
Еще одно отличие Scala от Java состоит в том, что в Scala-классах не может быть статических полей или методов. Вместо этого Scala позволяет создать singleton-объекты с помощью ключевого слова object. Singleton-объект нельзя, да и не нужно, создавать с помощью new. В сущности он автоматически создается при первом использовании, и как следует из слова “singleton”, он может существовать только в одном экземпляре. Singleton-объект может иметь то же имя, что и класс. Компилятор Scala трансформирует поля и методы singleton-объекта в статические поля и методы результирующего бинарного Java-класса. Создайте файл WorldlyGreeter.scala со следующим кодом:
В этом файле вы определяете класс с помощью ключевого слова class, и singleton-объект с помощью ключевого слова object. Оба типа называются WorldlyGreeter. С точки зрения Java-программиста это можно рассматривать следующим образом: любые статические методы, которые в Java вы поместили бы в класс WorldlyGreeter, в Scala вы помещаете в singleton-объект WorldlyGreeter. На самом деле, когда компилятор Scala создает байткод для этого файла, он создает Java-класс WorldlyGreeter, который содержит экземплярный метод greet (определенный в классе WorldlyGreeter в исходном коде Scala) и статический метод worldify (определенный в singleton-объекте WorldlyGreeter). Заметьте также, что в первой строке метода greet класса WorldlyGreeter вызывается метод worldify singleton-объекта, с помощью синтаксиса, похожего на способ вызова статических методов в Java: имя singleton-объекта, точка и имя метода.
Чтобы исполнить этот код, придется создать приложение. Создайте файл WorldlyApp.scala со следующим кодом:
Ни WorldlyGreeter.scala, ни WorldlyApp.scala не являются скриптами, поскольку кончаются определениями. Скрипт же должен заканчиваться результирующим выражением. То есть если попробовать запустить один из этих файлов как скрипт, например, так:
Интерпретатор Scala пожалуется, что WorldlyGreeter.scala не заканчиваться результирующим выражением. Вместо этого вам потребуется скомпилировать эти файлы с помощью компилятора Scala, а затем запустить получившиеся файлы классов. Один из способов сделать это – использовать scalac, основного компилятора Scala. Просто введите:
Учитывая, что компилятор scalac запускает новый экземпляр JVM при каждом его вызове, и что JVM часто имеет заметную задержку запуска, дистрибутив Scala также включает daemon-компилятор Scala по имени fsc (быстрый компилятор Scala). Он используется так:
Фактический механизм, используемый программой scala при «интерпретации» исходного файла Scala, состоит в том, что исходный текст Scala компилируется в байткод в памяти, загружается немедленно через загрузчик класса, и исполняется.
Аналогично Java, любой Scala-класс с методом main, принимающим один параметр типа Array[String] и возвращающим Unit, может служить точкой входа приложения.
Как говорилось на шаге 2, Unit в Scala аналогичен void в Java. Если в Java метод main должен возвращать void, в Scala он должен возвращать Unit.
В данном примере у WorldlyApp есть метод main с подходящей сигнатурой, и можно запустить этот пример командой:
После чего вы, к глубочайшему своему изумлению, увидите:
Вы уже, возможно, видели такой результат раньше, но в этот раз он был сгенерирован необычным образом:
Шаг 12. Понимание trait-ов и mixin-ов
Как впервые говорилось в шаге 10, Scala включает конструкцию trait, по духу похожую на интерфейсы Java. Одно из главных различий между интерфейсами Java и trait-ами состоит в том, что если все методы в Java-интерфейсах по определению абстрактны, то методы trait-ов Scala могут иметь реальные тела с реальным кодом. Вот пример:
Независимо от того, как написан метод, суть в том, что trait-ы в Scala могут содержать не абстрактные методы. Еще одно различие между интерфейсами в Java и trait-ами в Scala – интерфейсы вы реализуете, а trait-ы – расширяете. Несмотря на эту разницу (implements/extends), наследование при определении новых типов в Scala работает аналогично Java. И в Java, и в Scala класс может расширять один (и только один) другой класс. В Java интерфейс может расширять ноль или более интерфейсов. Аналогично и в Scala, trait может расширять ноль или более trait-ов. В Java класс может реализовать несколько интерфейсов. Аналогично в Scala класс может расширять несколько trait-ов. Кстати, implements не является ключевым словом в Scala.
В этом примере класс Dog расширяет trait Friendly. Эти отношения наследования означают во многом то же, что и реализация интерфейса в Java. Вы можете хранить ссылку на экземпляр Dog в переменной или значении типа Friendly. Например:
Когда вы вызываете метод greet для ссылки Friendly pet, будет использоваться динамическое связывание, как и в Java, для определения, какая реализация метода должна быть вызвана. В данном случае класс Dog переопределяет метод greet, так что будет вызвана реализация greet из Dog. При исполнении этого кода вы должны получить Woof (реализация greet в Dog), а не Hi (реализация greet в Friendly). Обратите внимание, еще одно отличие от Java состоит в том, что чтобы переопределить метод в Scala нужно перед def написать override. Если попробовать переопределить метод, не указав override, Scala-код не скомпилируется.
Наконец, существенное различие между интерфейсами Java и trait-ами Scala состоит в том, что в Scala вы можете смешивать trait-ы во время создания экземпляра. Рассмотрим, например, следующий trait:
Trait ExclamatoryGreeter расширяет trait Friendly и переопределяет метод greet. Метод greet из ExclamatoryGreeter сперва вызывает метод greet суперкласса, присоединяет восклицательный знак к тому, что возвращает метод greet, и возвращает результирующую строку. Вы можете подмешать поведение этого trait-а во время создания экземпляра, используя ключевое слово with. Например:
При такой первой строке кода компилятор Scala создаст синтетический тип, который расширяет класс Dog и trait ExclamatoryGreeter, и создаст его экземпляр (синтетический тип генерируется автоматически компилятором, а не пишется вручную программистом). При вызове метода синтетического типа это приводит к вызову правильной реализации. При запуске этот код выведет «Woof!». Ссылка на новый экземпляр синтетического типа будет присвоена значению pup. Заметьте, что если бы тип pup не был явно определен как Friendly, компилятор Scala вывел бы тип pup как Dog with ExclamatoryGreeter.
Чтобы попробовать, создайте файл friendly.scala со следующим кодом:
При исполнении скрипт friendly.scala выведет:
Заключение
Как вы могли уловить из этой статьи, Scala обещает увеличение производительности труда программиста при сохранении инвестиций. Лежащая в основе Scala краткость синтаксиса и поддержка функционального стиля программирования обещают повысить производительность программирования по сравнению с Java, в то же время позволяя использовать все наработки платформы Java. Вы можете дополнять Java-код Scala-кодом и продолжать пользоваться преимуществами существующего Java-кода, множеством API, доступных на платформе Java, производительностью JVM и собственными знаниями Java.
Благодаря знаниям, полученным из этой статьи, вы должны быть способны начать использовать Scala для небольших задач, например, скриптов. В следующих статьях мы разберем затронутые здесь темы детальнее, и затронем другие темы, о которых здесь даже не упоминалось.