- Канал в slack (весна 2021):
#scala_spr2021
- Telegram для контактов:
@valentiay
- Почта для домашек:
valentiay@yandex.ru
Для сборки проекта используется sbt. Ниже несколько полезных команд.
# Перезагрузить конфигурацию проекта, если *.sbt-файлы, описывающие билд изменились
sbt reload
# Собрать проект (без тестов)
sbt compile
# Запустить конкретный Main-класс
sbt "runMain seminars.seminar1.HelloWorld1"
# Запустить все тесты
sbt test
# Запустить тесты для конкретного пакета (например, пакета с тестами на 1 дз)
sbt testOnly homeworks.homework1.*
# Запустить тесты на конкретный клас (например, на первую задачу первого дз)
sbt testOnly homeworks.homework1.task1Test
Также слайды и тесты можно запустить с помощью Intellij Idea с scala-плагином.
В проекте подключен линтер WartRemover.
При использовании одного из инструментов ниже, проект не соберется.
В большинстве случаев нужно отрефакторить код так,
чтобы этот инструмент не использовался.
Отключить ошибку можно аннотацией @SuppressWarnings(Array("org.wartremover.warts.All"))
,
перед этим лучше уточнить в чате, стоит ли так делать.
Если с рефакторингом возникают проблемы, тоже можно попросить помощи в чате.
Почти всегда тип можно привести без использования кастов.
Для чисел можно использовать встроенные методы .toChar
, .toInt
, toLong
и т.п.
Для апкаста можно указывать типы в функциях, например так:
import scala.util.Random
def nextLong: Long = Random.nextInt
При работе с эффектами можно использовать метод функтора .widen
:
import cats.effect.IO
import cats.syntax.applicative._
import cats.syntax.functor._
val a: IO[Option[String]] = None.pure[IO].widen
Вместо даункастов нужно использовать паттерн-матчинг.
.asInstanceOf
может использоваться для некоторых оптимизаций, например, newtype.
В функциональном программировании идиоматично использовать неизменяемые
струтуры данных. Это позволяет избежать многих ошибок и писать более читаемый код.
Подробнее здесь.
Почти все задачи решаются с помощью методов .map
, .filter
, .foldLeft
и т.п.
Изменияемые структуры данных используют для повышения производительности
в некторых случаях, но в нашем курсе таких задач нет.
Использование null
ведет к непредсказуемым исключениям.
Вместо него нужно использовать Option
.
При использовании return
появляются неожиданные точки выхода из программы,
что снижает читаемость кода. Значения должны возвращаться в конце блока.
Использование исключений, как и return
дает неожиданные точки выхода.
Вместо исключений нужно использовать Option
, Either
или средства библиотеки эффектов.
Аналогично MutableDataStructures
Чаще всего ведет к использованию изменяемых переменных и коллекций.
Вместо while
нужно использовать хвостовую рекурсию или .foldLeft
и подобные.
def foo: Int = {
val as = scala.collection.mutable.ListBuffer.empty[Int]
as += 1
as += null.asInstanceOf[Int]
as += 2
var i = 0
while (i < as.length) {
val a = as(i)
if (a == null) throw new NullPointerException("Unexpected null!")
if (a % 2 == 0) return a
i += 1
}
0
}