8000 Add context params in ru (#2878) · OlegAlexander/docs.scala-lang@5d13fe8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5d13fe8

Browse files
Add context params in ru (scala#2878)
* Update compound-types.md in russian * Add ca-context-bounds.md, ca-context-parameters.md in russian * Add ca-context-bounds.md, ca-context-parameters.md in russian
1 parent f819c0e commit 5d13fe8

File tree

5 files changed

+340
-3
lines changed
  • _ru/scala3/book
  • 5 files changed

    +340
    -3
    lines changed

    _overviews/scala3-book/ca-context-bounds.md

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -2,7 +2,7 @@
    22
    title: Context Bounds
    33
    type: section
    44
    description: This page demonstrates Context Bounds in Scala.
    5-
    languages: [zh-cn]
    5+
    languages: [ru, zh-cn]
    66
    num: 62
    77
    previous-page: ca-context-parameters
    88
    next-page: ca-given-imports

    _overviews/scala3-book/ca-context-parameters.md

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -2,7 +2,7 @@
    22
    title: Context Parameters
    33
    type: section
    44
    description: This page demonstrates how to declare context parameters, and how the compiler infers them at call-site.
    5-
    languages: [zh-cn]
    5+
    languages: [ru, zh-cn]
    66
    num: 61
    77
    previous-page: ca-extension-methods
    88
    next-page: ca-context-bounds

    _ru/scala3/book/ca-context-bounds.md

    Lines changed: 141 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,141 @@
    1+
    ---
    2+
    layout: multipage-overview
    3+
    title: Контекстные границы
    4+
    scala3: true
    5+
    partof: scala3-book
    6+
    overview-name: "Scala 3 — Book"
    7+
    type: section
    8+
    description: В этой главе представлены контекстные границы в Scala 3.
    9+
    language: ru
    10+
    num: 62
    11+
    previous-page: ca-context-parameters
    12+
    next-page:
    13+
    ---
    14+
    15+
    Во многих ситуациях имя [контекстного параметра]({% link _overviews/scala3-book/ca-context-parameters.md %}#context-parameters)
    16+
    не нужно указывать явно, поскольку оно используется компилятором только в синтезированных аргументах для других параметров контекста.
    17+
    В этом случае вам не нужно определять имя параметра, а можно просто указать тип.
    18+
    19+
    ## Предыстория
    20+
    21+
    Например, рассмотрим метод `maxElement`, возвращающий максимальное значение в коллекции:
    22+
    23+
    {% tabs context-bounds-max-named-param class=tabs-scala-version %}
    24+
    25+
    {% tab 'Scala 2' %}
    26+
    27+
    ```scala
    28+
    def maxElement[A](as: List[A])(implicit ord: Ord[A]): A =
    29+
    as.reduceLeft(max(_, _)(ord))
    30+
    ```
    31+
    32+
    {% endtab %}
    33+
    34+
    {% tab 'Scala 3' %}
    35+
    36+
    ```scala
    37+
    def maxElement[A](as: List[A])(using ord: Ord[A]): A =
    38+
    as.reduceLeft(max(_, _)(using ord))
    39+
    ```
    40+
    41+
    {% endtab %}
    42+
    43+
    {% endtabs %}
    44+
    45+
    Метод `maxElement` принимает _контекстный параметр_ типа `Ord[A]` только для того,
    46+
    чтобы передать его в качестве аргумента методу `max`.
    47+
    48+
    Для полноты приведем определения `max` и `Ord`
    49+
    (обратите внимание, что на практике мы будем использовать существующий метод `max` для `List`,
    50+
    но мы создали этот пример для иллюстрации):
    51+
    52+
    {% tabs context-bounds-max-ord class=tabs-scala-version %}
    53+
    54+
    {% tab 'Scala 2' %}
    55+
    56+
    ```scala
    57+
    /** Определяет, как сравнивать значения типа `A` */
    58+
    trait Ord[A] {
    59+
    def greaterThan(a1: A, a2: A): Boolean
    60+
    }
    61+
    62+
    /** Возвращает максимальное из двух значений */
    63+
    def max[A](a1: A, a2: A)(implicit ord: Ord[A]): A =
    64+
    if (ord.greaterThan(a1, a2)) a1 else a2
    65+
    ```
    66+
    67+
    {% endtab %}
    68+
    69+
    {% tab 'Scala 3' %}
    70+
    71+
    ```scala
    72+
    /** Определяет, как сравнивать значения типа `A` */
    73+
    trait Ord[A]:
    74+
    def greaterThan(a1: A, a2: A): Boolean
    75+
    76+
    /** Возвращает максимальное из двух значений */
    77+
    def max[A](a1: A, a2: A)(using ord: Ord[A]): A =
    78+
    if ord.greaterThan(a1, a2) then a1 else a2
    79+
    ```
    80+
    81+
    {% endtab %}
    82+
    83+
    {% endtabs %}
    84+
    85+
    Обратите внимание, что метод `max` принимает контекстный параметр типа `Ord[A]`, как и метод `maxElement`.
    86+
    87+
    ## Пропуск контекстных аргументов
    88+
    89+
    Так как `ord` - это контекстный параметр в методе `max`,
    90+
    компилятор может предоставить его для нас в реализации `maxElement` при вызове `max`:
    91+
    92+
    {% tabs context-bounds-context class=tabs-scala-version %}
    93+
    94+
    {% tab 'Scala 2' %}
    95+
    96+
    ```scala
    97+
    def maxElement[A](as: List[A])(implicit ord: Ord[A]): A =
    98+
    as.reduceLeft(max(_, _))
    99+
    ```
    100+
    101+
    {% endtab %}
    102+
    103+
    {% tab 'Scala 3' %}
    104+
    105+
    ```scala
    106+
    def maxElement[A](as: List[A])(using Ord[A]): A =
    107+
    as.reduceLeft(max(_, _))
    108+
    ```
    109+
    110 10000 +
    Обратите внимание: поскольку нам не нужно явно передавать его методу `max`,
    111+
    мы можем не указывать его имя в определении метода `maxElement`.
    112+
    Это _анонимный параметр контекста_.
    113+
    114+
    {% endtab %}
    115+
    116+
    {% endtabs %}
    117+
    118+
    ## Границы контекста
    119+
    120+
    Учитывая написанное выше, _привязка к контексту_ — это сокращенный синтаксис
    121+
    для выражения шаблона "параметр контекста, применяемый к параметру типа".
    122+
    123+
    Используя привязку к контексту, метод `maxElement` можно записать следующим образом:
    124+
    125+
    {% tabs context-bounds-max-rewritten %}
    126+
    127+
    {% tab 'Scala 2 и 3' %}
    128+
    129+
    ```scala
    130+
    def maxElement[A: Ord](as: List[A]): A =
    131+
    as.reduceLeft(max(_, _))
    132+
    ```
    133+
    134+
    {% endtab %}
    135+
    136+
    {% endtabs %}
    137+
    138+
    Привязка типа `: Ord` к параметру типа `A` метода или класса указывает на параметр контекста с типом `Ord[A]`.
    139+
    Под капотом компилятор преобразует этот синтаксис в тот, который показан в разделе "Предыстория".
    140+
    141+
    Дополнительные сведения о границах контекста см. в разделе ["Что такое границы контекста?"]({% link _overviews/FAQ/index.md %}#what-are-context-bounds) раздел FAQ по Scala.
    Lines changed: 196 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,196 @@
    1+
    ---
    2+
    layout: multipage-overview
    3+
    title: Параметры контекста
    4+
    scala3: true
    5+
    partof: scala3-book
    6+
    overview-name: "Scala 3 — Book"
    7+
    type: section
    8+
    description: На этой странице показано, как объявлять параметры контекста и как компилятор выводит их на стороне вызова.
    9+
    language: ru
    10+
    num: 61
    11+
    previous-page: ca-extension-methods
    12+
    next-page: ca-context-bounds
    13+
    ---
    14+
    15+
    Scala предлагает две важные функции для контекстной абстракции:
    16+
    17+
    - **Параметры контекста** позволяют указать параметры, которые на стороне вызова могут быть опущены программистом
    18+
    и должны автоматически предоставляться контекстом.
    19+
    - **Экземпляры given** (в Scala 3) или **неявные определения** (в Scala 2) — это термины,
    20+
    которые компилятор Scala может использовать для заполнения отсутствующих аргументов.
    21+
    22+
    ## Параметры контекста
    23+
    24+
    При проектировании системы зачастую необходимо предоставлять контекстную информацию,
    25+
    такую как конфигурация или настройки, различным компонентам вашей системы.
    26+
    Одним из распространенных способов добиться этого является передача конфигурации
    27+
    в качестве дополнительного аргумента методам.
    28+
    29+
    В следующем примере мы определяем кейс класс `Config` для моделирования некоторой конфигурации веб-сайта
    30+
    и передаем ее в различных методах.
    31+
    32+
    {% tabs example %}
    33+
    {% tab 'Scala 2 и 3' %}
    34+
    35+
    ```scala
    36+
    case class Config(port: Int, baseUrl: String)
    37+
    38+
    def renderWebsite(path: String, config: Config): String =
    39+
    "<html>" + renderWidget(List("cart"), config) + "</html>"
    40+
    41+
    def renderWidget(items: List[String], config: Config): String = ???
    42+
    43+
    val config = Config(8080, "docs.scala-lang.org")
    44+
    renderWebsite("/home", config)
    45+
    ```
    46+
    47+
    {% endtab %}
    48+
    {% endtabs %}
    49+
    50+
    Предположим, что конфигурация не меняется на прот 179B яжении большей части нашей кодовой базы.
    51+
    Передача `config` каждому вызову метода (например `renderWidget`) становится очень утомительной
    52+
    и делает нашу программу более трудной для чтения, поскольку нам нужно игнорировать аргумент `config`.
    53+
    54+
    ### Установка параметров как контекстных
    55+
    56+
    Мы можем пометить некоторые параметры наших методов как _контекстные_.
    57+
    58+
    {% tabs 'contextual-parameters' class=tabs-scala-version %}
    59+
    {% tab 'Scala 2' %}
    60+
    61+
    ```scala
    62+
    def renderWebsite(path: String)(implicit config: Config): String =
    63+
    "<html>" + renderWidget(List("cart")) + "</html>"
    64+
    // ^
    65+
    // аргумент config больше не требуется
    66+
    67+
    def renderWidget(items: List[String])(implicit config: Config): String = ???
    68+
    ```
    69+
    70+
    {% endtab %}
    71+
    {% tab 'Scala 3' %}
    72+
    73+
    ```scala
    74+
    def renderWebsite(path: String)(using config: Config): String =
    75+
    "<html>" + renderWidget(List("cart")) + "</html>"
    76+
    // ^
    77+
    // аргумент config больше не требуется
    78+
    79+
    def renderWidget(items: List[String])(using config: Config): String = ???
    80+
    ```
    81+
    82+
    {% endtab %}
    83+
    {% endtabs %}
    84+
    85+
    Начав секцию параметров с ключевого слова `using` в Scala 3 или `implicit` в Scala 2, мы сообщаем компилятору,
    86+
    что на стороне вызова он должен автоматически найти аргумент с необходимым типом.
    87+
    Таким образом, компилятор Scala выполняет **вывод термов**.
    88+
    89+
    При вызове `renderWidget(List("cart"))` компилятор Scala увидит, что в области видимости есть терм типа `Config`
    90+
    (в нашем случае - `config`) и автоматически предоставит его для `renderWidget`.
    91+
    Таким образом, программа эквивалентна приведенной выше.
    92+
    93+
    На самом деле, поскольку в реализации `renderWebsite` больше не нужно ссылаться на `config`,
    94+
    мы можем даже опустить его имя в подписи в Scala 3:
    95+
    96+
    {% tabs 'anonymous' %}
    97+
    {% tab 'Только в Scala 3' %}
    98+
    99+
    ```scala
    100+
    // нет необходимости придумывать имя параметра
    101+
    // vvvvvvvvvvvvv
    102+
    def renderWebsite(path: String)(using Config): String =
    103+
    "<html>" + renderWidget(List("cart")) + "</html>"
    104+
    ```
    105+
    106+
    {% endtab %}
    107+
    {% endtabs %}
    108+
    109+
    В Scala 2 именовать неявные параметры по-прежнему необходимо.
    110+
    111+
    ### Явное указание контекстных параметров
    112+
    113+
    Мы увидели, как _абстрагироваться_ от контекстных параметров
    114+
    и что компилятор Scala может автоматически предоставлять нам аргументы.
    115+
    Но как мы можем указать, какую конфигурацию использовать для нашего вызова `renderWebsite`?
    116+
    117+
    {% tabs 'explicit' class=tabs-scala-version %}
    118+
    {% tab 'Scala 2' %}
    119+
    120+
    Мы явно указываем значение аргумента, как если бы это был обычный аргумент:
    121+
    122+
    ```scala
    123+
    renderWebsite("/home")(config)
    124+
    ```
    125+
    126+
    {% endtab %}
    127+
    {% tab 'Scala 3' %}
    128+
    129+
    Подобно тому, как мы указали наш раздел параметров с помощью `using`,
    130+
    мы также можем явно указать контекстные параметры с помощью `using`:
    131+
    132+
    ```scala
    133+
    renderWebsite("/home")(using config)
    134+
    ```
    135+
    136+
    {% endtab %}
    137+
    {% endtabs %}
    138+
    139+
    Явное предоставление контекстных параметров может быть полезно,
    140+
    когда у нас в области видимости есть несколько разных значений,
    141+
    подходящих по типу, и мы хотим убедиться в корректности передачи параметра методу.
    142+
    143+
    Для всех остальных случаев, как мы увидим в следующем разделе,
    144+
    есть еще один способ ввести контекстуальные значения в область видимости.
    145+
    146+
    ## Экземпляры given (определения implicit в Scala 2)
    147+
    148+
    Мы видели, что можем явно передавать аргументы в качестве контекстных параметров.
    149+
    Однако, если для определенного типа существует _единственное каноническое значение_,
    150+
    есть другой предпочтительный способ сделать его доступным для компилятора Scala:
    151+
    пометив его как `given` в Scala 3 или `implicit` в Scala 2.
    152+
    153+
    {% tabs 'instances' class=tabs-scala-version %}
    154+
    {% tab 'Scala 2' %}
    155+
    156+
    ```scala
    157+
    implicit val config: Config = Config(8080, "docs.scala-lang.org")
    158+
    // ^^^^^^
    159+
    // это значение, которое выведет компилятор Scala
    160+
    // в качестве аргумента контекстного параметра типа Config
    161+
    ```
    162+
    163+
    {% endtab %}
    164+
    {% tab 'Scala 3' %}
    165+
    166+
    ```scala
    167+
    val config = Config(8080, "docs.scala-lang.org")
    168+
    169+
    // это тип, который мы хотим предоставить для канонического значения
    170+
    // vvvvvv
    171+
    given Config = config
    172+
    // ^^^^^^
    173+
    // это значение, которое выведет компилятор Scala
    174+
    // в качестве аргумента контекстного параметра типа Config
    175+
    ```
    176+
    177+
    {% endtab %}
    178+
    {% endtabs %}
    179+
    180+
    В приведенном выше примере мы указываем, что всякий раз,
    181+
    когда в текущей области видимости опущен контекстный параметр типа `Config`,
    182+
    компилятор должен вывести `config` в качестве аргумента.
    183+
    184+
    Определив каноническое значение для типа CC60 `Config`,
    185+
    мы можем вызвать `renderWebsite` следующим образом:
    186+
    187+
    ```scala
    188+
    renderWebsite("/home")
    189+
    // ^
    190+
    // снова без аргумента
    191+
    ```
    192+
    193+
    Подробное руководство о том, где Scala ищет канонические значения, можно найти в [FAQ]({% link _overviews/FAQ/index.md %}#where-does-scala-look-for-implicits).
    194+
    195+
    [reference]: {{ site.scala3ref }}/overview.html
    196+
    [blog-post]: /2020/11/06/explicit-term-inference-in-scala-3.html

    _ru/scala3/book/ca-extension-methods.md

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -9,7 +9,7 @@ description: В этой главе представлена работа мет
    99
    language: ru
    1010
    num: 60
    1111
    previous-page: ca-contextual-abstractions-intro
    12-
    next-page:
    12+
    next-page: ca-context-parameters
    1313
    versionSpecific: true
    1414
    ---
    1515

    0 commit comments

    Comments
     (0)
    0