From 5bb982dd2f2867e27333cd33755badc3cee83191 Mon Sep 17 00:00:00 2001 From: Artem Korsakov Date: Mon, 4 Mar 2024 11:53:55 +0300 Subject: [PATCH] Update ru pages (#2988) --- .../concrete-parallel-collections.md | 93 +++++++++---------- _ru/scala3/book/fp-intro.md | 9 +- _ru/scala3/book/methods-main-methods.md | 77 ++++++++++----- _ru/scala3/book/types-others.md | 2 + _ru/scala3/guides/scaladoc/settings.md | 2 + _ru/tour/named-arguments.md | 31 +++++-- 6 files changed, 128 insertions(+), 86 deletions(-) diff --git a/_ru/overviews/parallel-collections/concrete-parallel-collections.md b/_ru/overviews/parallel-collections/concrete-parallel-collections.md index b6170ffe1..1bda571a8 100644 --- a/_ru/overviews/parallel-collections/concrete-parallel-collections.md +++ b/_ru/overviews/parallel-collections/concrete-parallel-collections.md @@ -43,10 +43,10 @@ num: 2 [ParRange](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/parallel/immutable/ParRange.html) представляет собой упорядоченную последовательность элементов, отстоящих друг от друга на одинаковые промежутки. Параллельный диапазон создается подобно последовательному [Range](https://www.scala-lang.org/api/{{ site.scala-212-version }}/scala/collection/immutable/Range.html): - scala> 1 to 3 par + scala> (1 to 3).par res0: scala.collection.parallel.immutable.ParRange = ParRange(1, 2, 3) - scala> 15 to 5 by -2 par + scala> (15 to 5 by -2).par res1: scala.collection.parallel.immutable.ParRange = ParRange(15, 13, 11, 9, 7, 5) Подобно тому, как последовательные диапазоны не имеют строителей, параллельные диапазоны не имеют [компоновщиков]({{ site.baseurl }}/ru/overviews/parallel-collections/architecture.html). При создании отображения (mapping) элементов параллельного диапазона получается параллельный вектор. Последовательные и параллельные диапазоны могут эффективно преобразовываться друг в друга вызовами методов `seq` и `par`. @@ -72,7 +72,7 @@ num: 2 scala> val phs = scala.collection.parallel.immutable.ParHashSet(1 until 1000: _*) phs: scala.collection.parallel.immutable.ParHashSet[Int] = ParSet(645, 892, 69, 809, 629, 365, 138, 760, 101, 479,... - scala> phs map { x => x * x } sum + scala> phs.map(x => x * x).sum res0: Int = 332833500 [Компоновщики]({{ site.baseurl }}/overviews/parallel-collections/architecture.html) параллельных хэш-деревьев действуют аналогично компоновщикам хэш-таблиц, а именно предварительно распределяют элементы по блокам, а после этого параллельно составляют результирующее хэш-дерево, назначая обработку различных блоков разным процессорам, каждый из которых независимо собирает свое поддерево. @@ -88,19 +88,19 @@ num: 2 scala> while (numbers.nonEmpty) { | numbers foreach { case (num, sqrt) => - | val nsqrt = 0.5 * (sqrt + num / sqrt) - | numbers(num) = nsqrt - | if (math.abs(nsqrt - sqrt) < 0.01) { - | println(num, nsqrt) - | numbers.remove(num) - | } - | } - | } - (1.0,1.0) + | val nsqrt = 0.5 * (sqrt + num / sqrt) + | numbers(num) = nsqrt + | if (math.abs(nsqrt - sqrt) < 0.01) { + | println(num, nsqrt) + | numbers.remove(num) + | } + | } + | } + (1.0,1.0) (2.0,1.4142156862745097) (7.0,2.64576704419029) (4.0,2.0000000929222947) - ... + ... [Компоновщики]({{ site.baseurl }}/ru/overviews/parallel-collections/architecture.html) реализованы как `TrieMap`-- так как эта структура является многопоточной, при вызове метода трансформации создается только один компоновщик, разделяемый всеми процессорами. @@ -110,53 +110,52 @@ num: 2 Характеристики производительности последовательных типов (sequence types): -| | head | tail | apply | update| prepend | append | insert | -| -------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | -| `ParArray` | C | L | C | C | L | L | L | -| `ParVector` | eC | eC | eC | eC | eC | eC | - | -| `ParRange` | C | C | C | - | - | - | - | +| | head | tail | apply | update | prepend | append | insert | +| ----------- | ---- | ---- | ----- | ------ | ------- | ------ | ------ | +| `ParArray` | C | L | C | C | L | L | L | +| `ParVector` | eC | eC | eC | eC | eC | eC | - | +| `ParRange` | C | C | C | - | - | - | - | Характеристики производительности множеств (set) и ассоциативных массивов (map): -| | lookup | add | remove | -| -------- | ---- | ---- | ---- | -| **неизменяемые** | | | | -| `ParHashSet`/`ParHashMap`| eC | eC | eC | -| **изменяемые** | | | | -| `ParHashSet`/`ParHashMap`| C | C | C | -| `ParTrieMap` | eC | eC | eC | - +| | lookup | add | remove | +| ------------------------- | ------ | --- | ------ | +| **неизменяемые** | | | | +| `ParHashSet`/`ParHashMap` | eC | eC | eC | +| **изменяемые** | | | | +| `ParHashSet`/`ParHashMap` | C | C | C | +| `ParTrieMap` | eC | eC | eC | ### Расшифровка Обозначения в двух представленных выше таблицах означают следующее: -| | | -| --- | ---- | -| **C** | Операция (быстрая) выполняется за постоянное время. | -| **eC** | Операция выполняется за фактически постоянное время, но только при соблюдении некоторых предположений, например о максимальной длине вектора или распределении хэш-кодов.| +| | | +| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **C** | Операция (быстрая) выполняется за постоянное время. | +| **eC** | Операция выполняется за фактически постоянное время, но только при соблюдении некоторых предположений, например о максимальной длине вектора или распределении хэш-кодов. | | **aC** | Операция выполняется за амортизированное постоянное время. Некоторые вызовы операции могут выполняться медленнее, но при подсчете времени выполнения большого количества операций выходит, что в среднем на операцию требуется постоянное время. | -| **Log** | Операция занимает время, пропорциональное логарифму размера коллекции. | -| **L** | Операция линейна, то есть занимает время, пропорциональное размеру коллекции. | -| **-** | Операция не поддерживается. | +| **Log** | Операция занимает время, пропорциональное логарифму размера коллекции. | +| **L** | Операция линейна, то есть занимает время, пропорциональное размеру коллекции. | +| **-** | Операция не поддерживается. | Первая таблица трактует последовательные типы-- изменяемые и неизменяемые-- в контексте выполнения следующих операций: -| | | -| --- | ---- | -| **head** | Получение первого элемента последовательности. | -| **tail** | Получение новой последовательности, состоящей из всех элементов исходной, кроме первого. | -| **apply** | Индексирование. | -| **update** | Функциональное обновление (с помощью `updated`) для неизменяемых последовательностей, обновление с побочными действиями (с помощью `update`) для изменяемых. | -| **prepend**| Добавление элемента в начало последовательности. Для неизменяемых последовательностей создается новая последовательность, для изменяемых-- модифицируется существующая. | -| **append** | Добавление элемента в конец последовательности. Для неизменяемых последовательностей создается новая последовательность, для изменяемых-- модифицируется существующая. | -| **insert** | Вставка элемента в выбранную позицию последовательности. Поддерживается только изменяемыми последовательностями. | +| | | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **head** | Получение первого элемента последовательности. | +| **tail** | Получение новой последовательности, состоящей из всех элементов исходной, кроме первого. | +| **apply** | Индексирование. | +| **update** | Функциональное обновление (с помощью `updated`) для неизменяемых последовательностей, обновление с побочными действиями (с помощью `update`) для изменяемых. | +| **prepend** | Добавление элемента в начало последовательности. Для неизменяемых последовательностей создается новая последовательность, для изменяемых-- модифицируется существующая. | +| **append** | Добавление элемента в конец последовательности. Для неизменяемых последовательностей создается новая последовательность, для изменяемых-- модифицируется существующая. | +| **insert** | Вставка элемента в выбранную позицию последовательности. Поддерживается только изменяемыми последовательностями. | Вторая таблица рассматривает изменяемые и неизменяемые множества и ассоциативные массивы в контексте следующих операций: -| | | -| --- | ---- | +| | | +| ---------- | ---------------------------------------------------------------------------------------------- | | **lookup** | Проверка принадлежности элемента множеству, или получение значения, ассоциированного с ключом. | -| **add** | Добавление нового элемента во множество или новой пары ключ/значение в ассоциативный массив. | -| **remove** | Удаление элемента из множества или ключа из ассоциативного массива. | -| **min** | Минимальный элемент множества или минимальный ключ ассоциативного массива. | +| **add** | Добавление нового элемента во множество или новой пары ключ/значение в ассоциативный массив. | +| **remove** | Удаление элемента из множества или ключа из ассоциативного массива. | +| **min** | Минимальный элемент множества или минимальный ключ ассоциативного массива. | diff --git a/_ru/scala3/book/fp-intro.md b/_ru/scala3/book/fp-intro.md index a8a44521a..5c9b3f5fa 100644 --- a/_ru/scala3/book/fp-intro.md +++ b/_ru/scala3/book/fp-intro.md @@ -12,16 +12,15 @@ previous-page: collections-summary next-page: fp-what-is-fp --- - -Scala позволяет писать код в стиле объектно-ориентированного программирования (ООП), -в стиле функционального программирования (ФП), а также в гибридном стиле, используя оба подхода в комбинации. -По словам [Martin Odersky](https://twitter.com/alexelcu/status/996408359514525696), +Scala позволяет писать код в стиле объектно-ориентированного программирования (ООП), +в стиле функционального программирования (ФП), а также в гибридном стиле, используя оба подхода в комбинации. +По словам Martin Odersky, сущность Scala — это слияние функционального и объектно-ориентированного программирования в типизированной среде: - Функции для логики - Объекты для модульности -В этой главе предполагается, что вы знакомы с ООП и менее знакомы с ФП, +В этой главе предполагается, что вы знакомы с ООП и менее знакомы с ФП, поэтому в ней представлено краткое введение в несколько основных концепций функционального программирования: - Что такое функциональное программирование? diff --git a/_ru/scala3/book/methods-main-methods.md b/_ru/scala3/book/methods-main-methods.md index 46844f648..cd6342216 100644 --- a/_ru/scala3/book/methods-main-methods.md +++ b/_ru/scala3/book/methods-main-methods.md @@ -14,7 +14,7 @@ next-page: methods-summary
Написание однострочных программ только в Scala 3
-Scala 3 предлагает следующий способ определения программ, которые можно вызывать из командной строки: +Scala 3 предлагает следующий способ определения программ, которые можно вызывать из командной строки: добавление аннотации `@main` к методу превращает его в точку входа исполняемой программы: {% tabs method_1 %} @@ -27,7 +27,7 @@ Scala 3 предлагает следующий способ определен {% endtab %} {% endtabs %} -Для запуска программы достаточно сохранить эту строку кода в файле с именем, например, _Hello.scala_ +Для запуска программы достаточно сохранить эту строку кода в файле с именем, например, _Hello.scala_ (имя файла необязательно должно совпадать с именем метода) и запустить с помощью `scala`: ```bash @@ -35,8 +35,8 @@ $ scala Hello.scala Hello, World ``` -Аннотированный метод `@main` может быть написан либо на верхнем уровне (как показано), -либо внутри статически доступного объекта. +Аннотированный метод `@main` может быть написан либо на верхнем уровне (как показано), +либо внутри статически доступного объекта. В любом случае имя программы - это имя метода без каких-либо префиксов объектов. Узнайте больше об аннотации `@main`, прочитав следующие разделы или посмотрев это видео: @@ -47,7 +47,7 @@ Hello, World ### Аргументы командной строки -Метод `@main` может обрабатывать аргументы командной строки с различными типами. +Метод `@main` может обрабатывать аргументы командной строки с различными типами. Например, данный метод `@main`, который принимает параметры `Int`, `String` и дополнительные строковые параметры: {% tabs method_2 %} @@ -78,15 +78,15 @@ $ scala happyBirthday 23 Lisa Peter Happy 23rd Birthday, Lisa and Peter! ``` -Как показано, метод `@main` может иметь произвольное количество параметров. -Для каждого типа параметра должен существовать [given экземпляр][given] -класса типа `scala.util.CommandLineParser.FromString`, который преобразует аргумент из `String` в требуемый тип параметра. -Также, как показано, список параметров основного метода может заканчиваться повторяющимся параметром типа `String*`, +Как показано, метод `@main` может иметь произвольное количество параметров. +Для каждого типа параметра должен существовать [given экземпляр][given] +класса типа `scala.util.CommandLineParser.FromString`, который преобразует аргумент из `String` в требуемый тип параметра. +Также, как показано, список параметров основного метода может заканчиваться повторяющимся параметром типа `String*`, который принимает все оставшиеся аргументы, указанные в командной строке. -Программа, реализованная с помощью метода `@main`, проверяет, -что в командной строке достаточно аргументов для заполнения всех параметров, -и что строки аргументов могут быть преобразованы в требуемые типы. +Программа, реализованная с помощью метода `@main`, проверяет, +что в командной строке достаточно аргументов для заполнения всех параметров, +и что строки аргументов могут быть преобразованы в требуемые типы. Если проверка завершается неудачей, программа завершается с сообщением об ошибке: ``` @@ -97,20 +97,47 @@ $ scala happyBirthday sixty Fred Illegal command line: java.lang.NumberFormatException: For input string: "sixty" ``` +## Пользовательские типы как параметры + +Как упоминалось выше, компилятор ищет заданный экземпляр класса типов `scala.util.CommandLineParser.FromString` +для типа аргумента. Например, предположим, что у вас есть собственный тип `Color`, +который вы хотите использовать в качестве параметра. +Вы можете сделать это, как показано ниже: + +{% tabs method_3 %} +{% tab 'Только в Scala 3' for=method_3 %} + +```scala +enum Color: + case Red, Green, Blue + +given ComamndLineParser.FromString[Color] with + def fromString(value: String): Color = Color.valueOf(value) + +@main def run(color: Color): Unit = + println(s"The color is ${color.toString}") +``` + +{% endtab %} +{% endtabs %} + +Это работает одинаково для ваших собственных пользовательских типов в вашей программе, +а также для типов, которые можно использовать из другой библиотеки. + ## Детали Компилятор Scala генерирует программу из `@main` метода `f` следующим образом: - он создает класс с именем `f` в пакете, где был найден метод `@main`. -- класс имеет статический метод `main` с обычной сигнатурой Java `main` метода: +- класс имеет статический метод `main` с обычной сигнатурой Java `main` метода: принимает `Array[String]` в качестве аргумента и возвращает `Unit`. -- сгенерированный `main` метод вызывает метод `f` с аргументами, +- сгенерированный `main` метод вызывает метод `f` с аргументами, преобразованными с помощью методов в объекте `scala.util.CommandLineParser.FromString`. Например, приведенный выше метод `happyBirthday` генерирует дополнительный код, эквивалентный следующему классу: -{% tabs method_3 %} -{% tab 'Только в Scala 3' for=method_3 %} +{% tabs method_4 %} +{% tab 'Только в Scala 3' for=method_4 %} ```scala final class happyBirthday { @@ -127,9 +154,9 @@ final class happyBirthday { } ``` -> Примечание: В этом сгенерированном коде модификатор `` выражает, -> что `main` метод генерируется как статический метод класса `happyBirthday`. -> Эта функция недоступна для пользовательских программ в Scala. +> Примечание: В этом сгенерированном коде модификатор `` выражает, +> что `main` метод генерируется как статический метод класса `happyBirthday`. +> Эта функция недоступна для пользовательских программ в Scala. > Вместо неё обычные “статические” члены генерируются в Scala с использованием `object`. {% endtab %} @@ -137,16 +164,16 @@ final class happyBirthday { ## Обратная совместимость со Scala 2 -`@main` методы — это рекомендуемый способ создания программ, вызываемых из командной строки в Scala 3. +`@main` методы — это рекомендуемый способ создания программ, вызываемых из командной строки в Scala 3. Они заменяют предыдущий подход, который заключался в создании `object`, расширяющего класс `App`: -Прежняя функциональность `App`, основанная на "волшебном" `DelayedInit trait`, больше недоступна. +Прежняя функциональность `App`, основанная на "волшебном" `DelayedInit trait`, больше недоступна. `App` все еще существует в ограниченной форме, но не поддерживает аргументы командной строки и будет объявлен устаревшим в будущем. -Если программам необходимо выполнять перекрестную сборку между Scala 2 и Scala 3, +Если программам необходимо выполнять перекрестную сборку между Scala 2 и Scala 3, вместо этого рекомендуется использовать `object` с явным методом `main` и одним аргументом `Array[String]`: -{% tabs method_4 %} +{% tabs method_5 %} {% tab 'Scala 2 и 3' %} ```scala @@ -159,13 +186,13 @@ object happyBirthday { } ``` -> обратите внимание, что здесь мы используем `:_*` для передачи переменного числа аргументов, +> обратите внимание, что здесь мы используем `:_*` для передачи переменного числа аргументов, > который остается в Scala 3 для обратной совместимости. {% endtab %} {% endtabs %} -Если вы поместите этот код в файл с именем _happyBirthday.scala_, то сможете скомпилировать его с `scalac` +Если вы поместите этот код в файл с именем _happyBirthday.scala_, то сможете скомпилировать его с `scalac` и запустить с помощью `scala`, как показывалось ранее: ```bash diff --git a/_ru/scala3/book/types-others.md b/_ru/scala3/book/types-others.md index 5f0151483..131bdd403 100644 --- a/_ru/scala3/book/types-others.md +++ b/_ru/scala3/book/types-others.md @@ -24,5 +24,7 @@ versionSpecific: true - Вид полиморфизма Дополнительные сведения об этих типах см. в [Справочной документации Scala 3][reference]. +Для singleton типов см. раздел [literal types](https://scala-lang.org/files/archive/spec/3.4/03-types.html#literal-types) +спецификации Scala 3, а для уточненных типов — раздел [refined types](https://scala-lang.org/files/archive/spec/3.4/03-types.html). [reference]: {{ site.scala3ref }}/overview.html diff --git a/_ru/scala3/guides/scaladoc/settings.md b/_ru/scala3/guides/scaladoc/settings.md index c36dedb13..e8d68554c 100644 --- a/_ru/scala3/guides/scaladoc/settings.md +++ b/_ru/scala3/guides/scaladoc/settings.md @@ -40,6 +40,8 @@ Compile / doc / scalacOptions ++= Seq("-project", "my-project"), ##### -project-logo Логотип проекта, который появляется в верхнем левом углу. +Для темной темы можно выделить отдельный логотип с суффиксом `_dark`. +Например, если есть логотип `mylogo.png`, то для темной темы предполагается `mylogo_dark.png`. Чтобы обеспечить совместимость с псевдонимами Scala2 с `-doc-logo` ##### -project-footer diff --git a/_ru/tour/named-arguments.md b/_ru/tour/named-arguments.md index 5b2376cf4..da9202a05 100644 --- a/_ru/tour/named-arguments.md +++ b/_ru/tour/named-arguments.md @@ -17,27 +17,40 @@ prerequisite-knowledge: function-syntax ```scala mdoc def printName(first: String, last: String): Unit = - println(first + " " + last) + println(s"$first $last") -printName("John", "Smith") // выводит "John Smith" -printName(first = "John", last = "Smith") // выводит "John Smith" -printName(last = "Smith", first = "John") // выводит "John Smith" +printName("John", "Public") // выводит "John Public" +printName(first = "John", last = "Public") // выводит "John Public" +printName(last = "Public", first = "John") // выводит "John Public" +printName("Elton", last = "John") // выводит "Elton John" ``` {% endtab %} {% endtabs %} -Обратите внимание, что при указании имени параметра, порядок аргумента может быть изменен. -Однако если какие-то аргументы именованные, а другие нет, -то аргументы без имени должны стоять на первом месте и располагаться в том порядке, в котором описаны параметры метода. +Это полезно, когда два параметра имеют один и тот же тип и аргументы могут быть случайно перепутаны. + +Обратите внимание, что именованные аргументы могут быть указаны в любом порядке. +Однако, если аргументы расположены не в порядке параметров метода (читается слева направо), +остальные аргументы должны быть названы. + +В следующем примере именованные аргументы позволяют опустить параметр `middle`. +В случае ошибки, если первый аргумент не на своем месте, необходимо будет указать второй аргумент. {% tabs named-arguments-when-error %} {% tab 'Scala 2 и 3' for=named-arguments-when-error %} ```scala mdoc:fail -printName(last = "Smith", "john") // ошибка: позиция после именованного аргумента +def printFullName(first: String, middle: String = "Q.", last: String): Unit = + println(s"$first $middle $last") + +printFullName(first = "John", last = "Public") // выводит "John Q. Public" +printFullName("John", last = "Public") // выводит "John Q. Public" +printFullName("John", middle = "Quincy", "Public") // выводит "John Quincy Public" +printFullName(last = "Public", first = "John") // выводит "John Q. Public" +printFullName(last = "Public", "John") // ошибка: позиция после именованного аргумента ``` {% endtab %} @@ -45,4 +58,4 @@ printName(last = "Smith", "john") // ошибка: позиция после и {% endtabs %} Именованные аргументы работают при вызове Java методов, но только в том случае, -если используемая Java библиотека была скомпилирована с `-parameters`. +если используемая Java библиотека была скомпилирована с флагом `-parameters`.