Skip to content

Commit 31fe9b8

Browse files
Add tabs in ru tour (#2880)
* Update compound-types.md in russian * Add tabs in ru tour * Add tabs in ru tour * Add tabs in ru tour * Add tabs in ru tour
1 parent 5d13fe8 commit 31fe9b8

File tree

6 files changed

+361
-27
lines changed

6 files changed

+361
-27
lines changed

_ru/tour/annotations.md

Lines changed: 143 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,44 @@ previous-page: by-name-parameters
99
---
1010

1111
Аннотации используются для передачи метаданных при объявлении. Например, аннотация `@deprecated` перед объявлением метода, заставит компилятор вывести предупреждение, если этот метод будет использован.
12-
```
12+
13+
{% tabs annotations_1 class=tabs-scala-version %}
14+
{% tab 'Scala 2' for=annotations_1 %}
15+
16+
```scala mdoc:fail
1317
object DeprecationDemo extends App {
1418
@deprecated("deprecation message", "release # which deprecates method")
1519
def hello = "hola"
1620

17-
hello
21+
hello
1822
}
1923
```
24+
25+
{% endtab %}
26+
{% tab 'Scala 3' for=annotations_1 %}
27+
28+
```scala
29+
object DeprecationDemo extends App:
30+
@deprecated("deprecation message", "release # which deprecates method")
31+
def hello = "hola"
32+
33+
hello
34+
```
35+
36+
{% endtab %}
37+
{% endtabs %}
38+
2039
Такой код скомпилируется, но компилятор выдаст предупреждение: "there was one deprecation warning".
2140

2241
Аннотация применяется к первому идущему после нее объявлению или определению. Допускается использование сразу нескольких аннотаций следующих друг за другом. Порядок, в котором приводятся аннотации, не имеет значения.
2342

2443
## Аннотации, обеспечивающие корректность работы кода
44+
2545
Некоторые аннотации приводят к невозможности компиляции, если условие (условия) не выполняется. Например, аннотация `@tailrec` гарантирует, что метод является [хвостовой рекурсией](https://ru.wikipedia.org/wiki/%D0%A5%D0%B2%D0%BE%D1%81%D1%82%D0%BE%D0%B2%D0%B0%D1%8F_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F). Хвостовая рекурсия помогает держать потребление памяти на постоянном уровне. Вот как она используется в методе, который вычисляет факториал:
2646

47+
{% tabs annotations_2 class=tabs-scala-version %}
48+
{% tab 'Scala 2' for=annotations_2 %}
49+
2750
```scala mdoc
2851
import scala.annotation.tailrec
2952

@@ -36,8 +59,30 @@ def factorial(x: Int): Int = {
3659
factorialHelper(x, 1)
3760
}
3861
```
39-
Метод `factorialHelper` имеет аннотацию `@tailrec`, которая гарантирует, что метод действительно является хвостовой рекурсией. Если бы мы изменили реализацию `factorialHelper` так как указано далее, то компиляция бы провалилась:
62+
63+
{% endtab %}
64+
{% tab 'Scala 3' for=annotations_2 %}
65+
66+
```scala
67+
import scala.annotation.tailrec
68+
69+
def factorial(x: Int): Int =
70+
71+
@tailrec
72+
def factorialHelper(x: Int, accumulator: Int): Int =
73+
if x == 1 then accumulator else factorialHelper(x - 1, accumulator * x)
74+
factorialHelper(x, 1)
4075
```
76+
77+
{% endtab %}
78+
{% endtabs %}
79+
80+
Метод `factorialHelper` имеет аннотацию `@tailrec`, которая гарантирует, что метод действительно является хвостовой рекурсией. Если бы мы изменили реализацию `factorialHelper` так как указано далее, то компиляция бы провалилась:
81+
82+
{% tabs annotations_3 class=tabs-scala-version %}
83+
{% tab 'Scala 2' for=annotations_3 %}
84+
85+
```scala mdoc:fail
4186
import scala.annotation.tailrec
4287

4388
def factorial(x: Int): Int = {
@@ -48,77 +93,155 @@ def factorial(x: Int): Int = {
4893
factorialHelper(x)
4994
}
5095
```
51-
Мы бы получили сообщение "Recursive call not in tail position"(Рекурсивный вызов не в хвостовой позиции).
5296

97+
{% endtab %}
98+
{% tab 'Scala 3' for=annotations_3 %}
99+
100+
```scala
101+
import scala.annotation.tailrec
102+
103+
def factorial(x: Int): Int =
104+
@tailrec
105+
def factorialHelper(x: Int): Int =
106+
if x == 1 then 1 else x * factorialHelper(x - 1)
107+
factorialHelper(x)
108+
```
109+
110+
{% endtab %}
111+
{% endtabs %}
112+
113+
Мы бы получили сообщение "Recursive call not in tail position"(Рекурсивный вызов не в хвостовой позиции).
53114

54115
## Аннотации, влияющие на генерацию кода
116+
117+
{% tabs annotations_4 class=tabs-scala-version %}
118+
{% tab 'Scala 2' for=annotations_4 %}
119+
55120
Некоторые аннотации типа `@inline` влияют на сгенерированный код (т.е. в результате сам код вашего jar-файл может отличаться). Такая аннотация означает вставку всего кода в тело метода вместо вызова. Полученный байт-код длиннее, но, надеюсь, работает быстрее. Использование аннотации `@inline` не гарантирует, что метод будет встроен, но заставит компилятор сделать это, если и только если будут соблюдены некоторые разумные требования к размеру сгенерированного кода.
56121

57-
### Java аннотации ###
122+
{% endtab %}
123+
{% tab 'Scala 3' for=annotations_4 %}
124+
125+
Некоторые аннотации типа `@main` влияют на сгенерированный код (т.е. в результате сам код вашего jar-файл может отличаться).
126+
Аннотация `@main` к методу создает исполняемую программу, которая вызывает метод как точку входа.
127+
128+
{% endtab %}
129+
{% endtabs %}
130+
131+
### Java аннотации
132+
58133
Есть некоторые отличия синтаксиса аннотаций, если пишется Scala код, который взаимодействует с Java.
59134

60135
**Примечание:**Убедитесь, что вы используете опцию `-target:jvm-1.8` с аннотациями Java.
61136

62137
Java имеет определяемые пользователем метаданные в виде [аннотаций](https://docs.oracle.com/javase/tutorial/java/annotations/). Ключевой особенностью аннотаций является то, что они задаются в виде пар ключ-значение для инициализации своих элементов. Например, если нам нужна аннотация для отслеживания источника какого-то класса, мы можем определить её как
63138

64-
```
139+
{% tabs annotations_5 %}
140+
{% tab 'Java' for=annotations_5 %}
141+
142+
```java
65143
@interface Source {
66-
public String URL();
144+
public String url();
67145
public String mail();
68146
}
69147
```
70148

149+
{% endtab %}
150+
{% endtabs %}
151+
71152
А затем использовать следующим образом
72153

73-
```
74-
@Source(URL = "https://coders.com/",
154+
{% tabs annotations_6 %}
155+
{% tab 'Java' for=annotations_6 %}
156+
157+
```java
158+
@Source(url = "https://coders.com/",
75159
76-
public class MyClass extends HisClass ...
160+
public class MyJavaClass extends TheirClass ...
77161
```
78162

163+
{% endtab %}
164+
{% endtabs %}
165+
79166
Использование аннотации в Scala похоже на вызов конструктора. Для создания экземпляра из Java аннотации необходимо использовать именованные аргументы:
80167

81-
```
82-
@Source(URL = "https://coders.com/",
168+
{% tabs annotations_7 %}
169+
{% tab 'Scala 2 и 3' for=annotations_7 %}
170+
171+
```scala
172+
@Source(url = "https://coders.com/",
83173
84174
class MyScalaClass ...
85175
```
86176

177+
{% endtab %}
178+
{% endtabs %}
179+
87180
Этот синтаксис достаточно перегруженный, если аннотация содержит только один элемент (без значения по умолчанию), поэтому, если имя указано как `value`, оно может быть применено в Java с помощью конструктора-подобного синтаксиса:
88181

89-
```
182+
{% tabs annotations_8 %}
183+
{% tab 'Java' for=annotations_8 %}
184+
185+
```java
90186
@interface SourceURL {
91187
public String value();
92188
public String mail() default "";
93189
}
94190
```
95191

192+
{% endtab %}
193+
{% endtabs %}
194+
96195
А затем можно использовать следующим образом
97196

98-
```
197+
{% tabs annotations_9 %}
198+
{% tab 'Java' for=annotations_9 %}
199+
200+
```java
99201
@SourceURL("https://coders.com/")
100-
public class MyClass extends HisClass ...
202+
public class MyJavaClass extends TheirClass ...
101203
```
102204

205+
{% endtab %}
206+
{% endtabs %}
207+
103208
В этом случае Scala предоставляет такую же возможность
104209

105-
```
210+
{% tabs annotations_10 %}
211+
{% tab 'Scala 2 и 3' for=annotations_10 %}
212+
213+
```scala
106214
@SourceURL("https://coders.com/")
107215
class MyScalaClass ...
108216
```
109217

218+
{% endtab %}
219+
{% endtabs %}
220+
110221
Элемент `mail` был указан со значением по умолчанию, поэтому нам не нужно явно указывать его значение. Мы не можем смешивать эти два стиля в Java:
111222

112-
```
223+
{% tabs annotations_11 %}
224+
{% tab 'Java' for=annotations_11 %}
225+
226+
```java
113227
@SourceURL(value = "https://coders.com/",
114228
115-
public class MyClass extends HisClass ...
229+
public class MyJavaClass extends TheirClass ...
116230
```
117231

232+
{% endtab %}
233+
{% endtabs %}
234+
118235
Scala обеспечивает большую гибкость в этом отношении
119236

120-
```
237+
{% tabs annotations_12 %}
238+
{% tab 'Scala 2 и 3' for=annotations_12 %}
239+
240+
```scala
121241
@SourceURL("https://coders.com/",
122242
123-
class MyScalaClass ...
243+
class MyScalaClass ...
124244
```
245+
246+
{% endtab %}
247+
{% endtabs %}

_ru/tour/by-name-parameters.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,24 @@ previous-page: operators
99
---
1010

1111
_Вызов параметров по имени_ - это когда значение параметра вычисляется только в момент вызова параметра. Этот способ противоположен _вызову по значению_. Чтоб вызов параметра был по имени, необходимо просто указать `=>` перед его типом.
12+
13+
{% tabs by-name-parameters_1 %}
14+
{% tab 'Scala 2 и 3' for=by-name-parameters_1 %}
15+
1216
```scala mdoc
1317
def calculate(input: => Int) = input * 37
1418
```
19+
20+
{% endtab %}
21+
{% endtabs %}
22+
1523
Преимущество вызова параметров по имени заключается в том, что они не вычисляются если не используются в теле функции. С другой стороны плюсы вызова параметров по значению в том, что они вычисляются только один раз.
1624

1725
Вот пример того, как мы можем реализовать условный цикл:
1826

27+
{% tabs by-name-parameters_2 class=tabs-scala-version %}
28+
{% tab 'Scala 2' for=by-name-parameters_2 %}
29+
1930
```scala mdoc
2031
def whileLoop(condition: => Boolean)(body: => Unit): Unit =
2132
if (condition) {
@@ -30,8 +41,29 @@ whileLoop (i > 0) {
3041
i -= 1
3142
} // выведет 2 1
3243
```
33-
Метод `whileLoop` использует несколько списков параметров - условие и тело цикла. Если `condition` является верным, выполняется `body`, а затем выполняется рекурсивный вызов whileLoop. Если `condition` является ложным, то тело никогда не вычисляется, тк у нас стоит `=>` перед типом `body`.
44+
45+
{% endtab %}
46+
{% tab 'Scala 3' for=by-name-parameters_2 %}
47+
48+
```scala
49+
def whileLoop(condition: => Boolean)(body: => Unit): Unit =
50+
if condition then
51+
body
52+
whileLoop(condition)(body)
53+
54+
var i = 2
55+
56+
whileLoop (i > 0) {
57+
println(i)
58+
i -= 1
59+
} // выведет 2 1
60+
```
61+
62+
{% endtab %}
63+
{% endtabs %}
64+
65+
Метод `whileLoop` использует несколько списков параметров - условие и тело цикла. Если `condition` является верным, выполняется `body`, а затем выполняется рекурсивный вызов whileLoop. Если `condition` является ложным, то тело никогда не вычисляется, тк у нас стоит `=>` перед типом `body`.
3466

3567
Теперь, когда мы передаем `i > 0` как наше условие `condition` и `println(i); i-= 1` как тело `body`, код ведет себя также как обычный цикл в большинстве языков программирования.
3668

37-
Такая возможность откладывать вычисления параметра до его использования может помочь повысить производительность, отсекая не нужные вычисления при определенных условиях.
69+
Такая возможность откладывать вычисления параметра до его использования может помочь повысить производительность, отсекая не нужные вычисления при определенных условиях.

0 commit comments

Comments
 (0)