Кафедра ИВТ и ПМ. Ветров С. В.
2023
object Program {
def main(args: Array[String]) = {
println("Hello, World!")
}
}
@main
def main(): Unit = {
println("Hello")
println("world!")
}
@main
def main() =
println("Hello")
println("world!")
Синтаксис без операторных скобок, с отступами (в стиле Python) и без указания возвращаемого типа функции.
@main
def main() =
println("Hello world!")
println("Hello world!")
@main
— аннотация, помечающая текущий метод как главную функцию программы. Тело функции начинается после =. Фигурные скобки вокруг тела писать необязательно.
@main
def main() =
println("Hello world!")
println("Hello world!")
@main
— аннотация, помечающая текущий метод как главную функцию программы. Тело функции начинается после =. Фигурные скобки вокруг тела писать необязательно.scala
package my_package
// my_code
// подключить всё пространство имён Math
import Math._ // Scala 2+
import Math.* // Scala 3
import Math.exp
// подключение нескольких имён отдельно
import Math.{PI, E}
// подключаются автоматически
java.lang.*
scala.*
val x: Int = 2.3 // ошибка: требуется явное преобразование в Int
val y: = 40+2; // Int
val|var name: type = value
Константа (immutable variable)
val my_const:Float = 333/106;
val my_const = 333/106; // автоматический вывод типа: Double
val my_const; // Ошибка: значение не задано
Переменная
var my_variable:Int = 0;
var my_variable = 0;
var my_variable:Int; // Ошибка: не указано начальное значение
var my_variable; // Ошибка: невозможно вывести тип
val b: Byte = 1
val i: Int = 1 // default for type inference
val l: Long = 1
val s: Short = 1
val d: Double = 2.0 // default for type inference
val f: Float = 3.0e2 // 3.0 * 10 ^ 2
val S0 = "I'am string"
// многострочный литерал
val quote = """The essence of Scala:
Fusion of functional and object-oriented
programming in a typed setting."""
// многострочный литерал, без пробелов вначале
val quote = """The essence of Scala:
|Fusion of functional and object-oriented
|programming in a typed setting.""".stripMargin
s, f
и raw
- префиксы для строк
s
- префиксы строки с интерполяцией
val name = "James"
println( s"Hello, $name" ) // Hello, James
// интерполяция с выражениями внутри {}
println( s"5 = ${2+2}" ) // Hello, James
// экранирование знака доллара
println( s"price = $$99.5" ) // price = $99.5
f
- префиксы строки с интерполяцией и форматированием
Параметры форматирование записываются после знака %
val height = 1.9d
val name = "James"
println(f"$name%s is $height%2.2f meters tall") // James is 1.90 meters tall
raw
- интерполяция аналогичная s
, но без служебных символов в строке
s"a\nb"
// Результат:
a
b
raw"a\nb"
// Результат:
a\nb
import scala.util.matching.Regex
// метод строки r создаст из неё экземпляр типа numberPattern
val number_r: Regex = "[0-9]".r
// Для записи метасимволов удобно использовать префикс raw
val time_r: Regex = raw"\d\d:\d\d".r
import scala.util.matching.Regex
// метод строки r создаст из неё экземпляр типа numberPattern
val number_r: Regex = "[0-9]".r
// проверка на полное соответствие
number_r.matches("7"); // true
number_r.matches("71"); // false
number_r.matches("number"); // false
import scala.util.matching.Regex
// метод строки r создаст из неё экземпляр типа numberPattern
val number_r: Regex = "[0-9]".r
// number_r.findAllIn("12 abc 3 8") -> итератор
for m <- number_r.findAllIn("12 abc 3 8") do
println(m)
Вывод
1
2
3
8
Возвращаемый итератор имеет метод .toList
println("Hello, World!")
print("Hello, World!")
Форматные строки
val p = 333.0 / 106 // 3.141509433962264
println( f"pi ≈ $p%7.3f" )
println( f"pi ≈ ${333.0/106}%7.3f" )
Вывод
pi ≈ 3.143
pi ≈ 3.143
// подключение трёх функций из пакета
import scala.io.StdIn.{readLine, readInt, readLong}
val s: String = readLine()
if/then/else
отсутствует return
for loops
while loops
try/catch/finally
for expressions
— генераторыmatch expressions
— сопоставление с образцом
if x < 0 then
println("negative")
else if x == 0 then
println("zero")
else
println("positive")
val minValue = if a < b then a else b
import scala.util.Random
val rand = Random
val a = rand.nextInt()
val b = rand.nextInt()
val max =
if (a > b) a
else b
// `i` is an integer
val day = i match
case 0 => "Sunday"
case 1 => "Monday"
case 2 => "Tuesday"
case 3 => "Wednesday"
case 4 => "Thursday"
case 5 => "Friday"
case 6 => "Saturday"
case _ => "invalid day" // the default, catch-all
val day = i match
case 0 | 6 => "Sunday or Saturday"
case 1 => "Monday"
case 2 => "Tuesday"
case 3 => "Wednesday"
case 4 => "Thursday"
case 5 => "Friday"
case _ => "invalid day" // the default, catch-all
Условие внутри case
import scala.util.Random
val x: Int = Random.nextInt(10)
println(x)
x match
case x if (x%2==0) => "even"
case 1 => "one"
case 3 => "three"
case _ => "other"
Вместо значения в case можно указать переменную, в которую это значение запишется. Так как переменная будет всегда равна проверяемому значению, такая ветка будет срабатывать всегда.
val day = i match
case 0 => "Sunday"
case 1 => "Monday"
case 2 => "Tuesday"
case 3 => "Wednesday"
case 4 => "Thursday"
case 5 => "Friday"
case 6 => "Saturday"
case x => s"$x - not a valid day number" // the default, catch-all
// x - локальная для case переменная,
// в которую извлекается проверяемая переменная
case class Email(sender: String, title: String, body: String)
// возможные варианты для сопоставляемой переменной:
// val x = new Email("Spammer", "Not a Spam", "Hello, dear friend")
val x = new Email("Manager", "important!!!!", "Hello, dear friend")
// val x = new Email("Manager2", "important!!!!", "Hello, dear friend")
// val x = new Email("Vasya", "qwerty", "Hello, dear friend")
// 2 или более восклицательных знака среди всего остального,
// выражение должно быть в скобках для обозначения места для подстановки строки
val title_reg = "(.*!{2,}.*)".r
// 2 или более восклицательных знака среди всего остального
val title_reg22 = ".*!{2,}.*".r
val action = x match
// проверка по полю sender, с извлечением значения из поля title
// в переменную title1
case Email("Spammer", title1, _) => s"send <$title1> to spam"
// проверка по последнему полю
case Email(_, _, "money") => "mark important"
// проверка по точному совпадению с первым полем,
// извлечение значения второго поля в title22,
// проверка по регулярному выражению
case Email("Manager", title_reg(title22), _) => "delete"
// значение для проверки в регулярном выражении можно и не извлекать
// в переменную, ведь и так понятно что туда подставлять
case Email("Manager2", title_reg22(), _) => "also delete"
// если ничего не сработало
case _ => "do nothing"
for i <- 1 to 10 do
println(i)
i <- ints
- генератор
val ints = List(1, 2, 3, 4, 5)
for i <- ints do
println(i)
val ints = List(1, 2, 3, 4, 5)
for
i <- ints
if i % 2 == 0
do
println(i)
Вывод
2
4
for
i <- 1 to 3
j <- 'a' to 'c'
do
println(s"i = $i, j = $j")
Вывод
i = 1, j = a
i = 1, j = b
i = 1, j = c
i = 2, j = a
i = 2, j = b
i = 2, j = c
i = 3, j = a
i = 3, j = b
i = 3, j = c
for
i <- 1 to 10
j <- 'a' to 'c'
if i % 2 == 0
if j != 'b'
do
println(s"i = $i, j = $j")
Вывод
i = 2, j = a
i = 2, j = c
i = 4, j = a
i = 4, j = c
i = 6, j = a
i = 6, j = c
i = 8, j = a
i = 8, j = c
i = 10, j = a
i = 10, j = c
val ints = List(1, 2, 3, 4, 5)
// Создание списка
val doubles = for i <- ints yield i * 2
// Результат List[Int] =
List(2, 4, 6, 8, 10)
Такая запись удобна для преобразования списков
val names = List("chris", "ed", "maurice")
val capNames = for name <- names yield name.capitalize
// Результат List[String] =
List(Chris, Ed, Maurice)