SVI 1 mese fa
parent
commit
b3cf126294
1 ha cambiato i file con 37 aggiunte e 39 eliminazioni
  1. 37 39
      doc/part01/ch09.md

+ 37 - 39
doc/part01/ch09.md

@@ -1,64 +1,64 @@
 # Глава 9. Шаблоны
 
-Что происходит, когда мы вызываем `putPixel` для координат, выходящих за границы экрана? Это зависит от реализации нашей библиотеки пикселей, но возможны три варианта:
+Что происходит, когда происходит вызывов `putPixel` для координат, выходящих за границы экрана? Это зависит от реализации библиотеки пикселей, но возможны три варианта:
 
 - 1 Ничего.
 - 2 Возникает исключение.
 - 3 Программа выходит из строя.
 
-In order to do “nothing” early returns can be a handy mechanism:
+Чтобы «ничего не делать», можно воспользоваться механизмом досрочного возврата.
 
 ```nim
 const
-    ScreenWidth = 1024 # 1
+    ScreenWidth  = 1024 # 1
     ScreenHeight = 768
 
 proc safePutPixel(x, y: int; col: Color) =
     if x < 0 or x >= ScreenWidth or
         y < 0 or y >= ScreenHeight:
-       return  # 2
+       return           # 2
     putPixel(x, y, col) # 3
 ```
 
-- 1 For simplicity, we assume a screen resolution of 1024x768 here. With const you can declare constants. A constant is comparable to a variable but its value cannot be changed and must be set at compile-time. The benefits of these restrictions will be explained later.
-- 2 If the coordinates are not within bounds return.
-- 3 Else call the putPixel proc.
+- 1 Для простоты предположем, что разрешение экрана составляет 1024x768. С помощью `const` можно объявлять константы. Константа похожа на переменную, но её значение нельзя изменить, оно должно быть задано во время компиляции. Преимущества этих ограничений будут приведены позже.
+- 2 Если координаты выходят за пределы допустимого диапазона, вернуть их.
+- 3 В противном случае вызвать процедуру `putPixel`.
 
-A program fragment like if not `inBounds(...)`: return is common in graphics programming and so one can desire to move it into a helper proc.
+Фрагмент программы, подобный `if not inBounds(...): return`, часто встречается в графическом программировании, поэтому может возникнуть желание вынести его в вспомогательную процедуру.
 
-Unfortunately, a return statement leaves the current proc and so code like the following has not the desired effect:
+К сожалению, оператор `return` завершает текущую процедуру, поэтому следующий код не дает желаемого результата:
 
 ```nim
-  proc boundsCheck(x, y: int) =
+proc boundsCheck(x, y: int) =
     if x < 0 or x >= ScreenWidth or
        y < 0 or y >= ScreenHeight:
-      return # 1
-  proc safePutPixel(x, y: int; col: Color) =
+      return            # 1
+proc safePutPixel(x, y: int; col: Color) =
     boundsCheck(x, y)
     putPixel(x, y, col)
 ```
 
-- 1 The return statements leaves boundsCheck but not safePutPixel!
+- 1 Оператор `return` возвращает `boundsCheck`, но не `safePutPixel`!
 
-Nim offers a construct which has the “inlining” semantics that we need: A template is syntactically much like a proc, but an invocation to a template means to expand the template's body at the call site:
+В языке **Nim** есть конструкция с нужной семантикой «встраивания»: шаблон синтаксически очень похож на процедуру, но вызов шаблона означает раскрытие его тела в месте вызова.
 
 ```nim
 template boundsCheck(a, b: int) = # 1
     if a < 0 or a >= ScreenWidth or
        b < 0 or b >= ScreenHeight:
-      return # 2
+      return                     # 2
 proc safePutPixel(x, y: int; col: Color) =
-    boundsCheck(x, y) # 3
+    boundsCheck(x, y)            # 3
     putPixel(x, y, col)
 ```
 
-- 1 A template of name boundsCheck with parameters named a and b of type `int` is declared.
-- 2 return inside a template means to return from the template`s caller.
-- 3 A template can be invoked just like a proc.
+- 1 Объявлен шаблон с именем `boundsCheck` с параметрами `a` и `b` типа `int`.
+- 2 `return` внутри шаблона означает возврат из вызывающей функции шаблона.
+- 3 Шаблон можно вызвать так же, как и процедуру.
 
-Even though boundsCheck(x, y) looks like a call, it’s not called, instead boundsCheck's body is inserted directly into safePutPixel. This insertion also does parameter substitutions; in our example the template parameter a is replaced by the procs parameter x and likewise is b replaced by y.
+Несмотря на то, что `boundsCheck(x, y)` выглядит как вызов, на самом деле он не вызывается, а тело `boundsCheck` вставляется непосредственно в `safePutPixel`. При вставке также происходит подстановка параметров: в нашем примере параметр шаблона a заменяется параметром процедуры `x`, а `b` — на `y`.
 
-A template is a simple form of a macro, it is most commonly used for control flow abstractions and one can pass multiple statements to a template easily:
+Шаблон — это простая форма макроса, которая чаще всего используется для абстракции потока управления. В шаблон можно легко передать несколько операторов:
 
 ```nim
 template wrap(body: untyped) =               # 1
@@ -66,32 +66,30 @@ template wrap(body: untyped) =               # 1
     body                                     # 3
 wrap:                                        # 4
     for i in 1..3:
-      let textToDraw = "Welcome to Nim for the " & $i & "th time!"
+      let textToDraw = "Добро пожаловать в Nim " & $i & " раз!"
       drawText 10, i*10, textToDraw, 8, Yellow
 ```
 
-- 1 The wrap templates takes a list of statements called body. The type untyped will be explained later.
-- 2 The `drawText` call runs
-- 3 before the statements that are passed via body are run.
-- 4 Via the syntax wrap: (note the colon) followed by the indented for loop we pass the for loop to the wrap template.
+- 1 Шаблон `wrap` принимает список операторов под названием `body`. Тип `untyped` будет описан позже
+- 2 Вызов `drawText` выполняется
+- 3 перед выполнением операторов, передаваемых через `body`
+- 4 С помощью синтаксической обёртки: (обратите внимание на двоеточие), за которой следует цикл `for` с отступом, мы передаём цикл `for` в шаблон обёртки.
 
-Even though templates are based on a conceptually quite simple substitution mechanism that is completely performed at compile-time, their power is surprising. With some experience they enable a programming style that lets us abstract away many details leading to shorter programs without negatively impacting the readability.
+Несмотря на то, что шаблоны основаны на концептуально довольно простом механизме подстановки, который полностью выполняется во время компиляции, их возможности поражают. При наличии некоторого опыта они позволяют использовать стиль программирования, который позволяет абстрагироваться от многих деталей, что приводит к сокращению кода без ущерба для читабельности.
 
-As an example we introduce a withColor environment. Inside this environment `putPixel` and `drawText` should use a specified color implicitly so that we don’t have to repeat the color argument again and again. We declare variants of `putPixel` and drawText as templates that use an undeclared colorContext variable:
+В качестве примера мы вводим окружение `withColor`. Внутри этого окружения `putPixel` и `drawText` должны неявно использовать указанный цвет, чтобы нам не приходилось повторять аргумент `color` снова и снова. Мы объявляем варианты `putPixel` и `drawText` как шаблоны, использующие необъявленную переменную `colorContext`:
 
 ```nim
 template putPixel(x, y: int) = putPixel(x, y, colorContext)               # 1
 template drawText(x, y: int; s: string) = drawText(x, y, s, colorContext) # 2
 ```
 
-- 1 The `putPixel` template which does not take a color delegates its work to the existing putPixel proc using the still undeclared colorContext color.
-- 2 Likewise does `drawText`.
+- 1 Шаблон `putPixel`, который не принимает цвет, делегирует свою работу существующей процедуре `putPixel`, используя все еще не объявленный параметр цвета `colorContext`.
+- 2 Аналогичным образом действует `drawText`.
 
-Even though putPixel and `drawText` are already in our scope, it is valid to use the same names again for different (but in this case related) operations. The disambiguate the invocations. In our case the disambiguation is simple: A call `putPixel(x, y, color)` resolves to `pixels.putPixel(x, y, color)`, whereas a call without a color parameter resolves to the newly introduced template of this name. The same applies for `drawText`.
-Templates can easily refer to undeclared entities because only a template
-expansion implies that the result is checked for semantics.
+Несмотря на то, что `putPixel` и `drawText` уже находятся в нашей области видимости, допустимо _снова_ использовать те же имена для _разных_ (но в данном случае связанных) операций. Это устраняет неоднозначность вызовов. В нашем случае устранить неоднозначность просто: вызов `putPixel(x, y, color)` разрешается в `pixels.putPixel(x, y, color)`, а вызов без параметра `color` разрешается во вновь созданный шаблон с таким же именем. То же самое относится к `drawText`. Шаблоны могут легко ссылаться на необъявленные сущности, поскольку только при раскрытии шаблона результат проверяется на соответствие семантике.
 
-The `colorContext` variable is declared inside the withColor environment. It is marked with inject so that it is visible inside the body:
+Переменная `colorContext` объявлена внутри окружения `withColor`. Она помечена как `inject`, чтобы быть видимой внутри тела функции:
 
 ```nim
 template withColor(col: Color; body: untyped) = # 1
@@ -102,12 +100,12 @@ withColor Blue:                                 # 3
     drawText 10, 10, "abc", 12
 ```
 
-- 1 `withColor` is a template that takes both a color and a `body` of code.
-- 2 `colorContext` is injected into body. Without the `.inject` annotation, `putPixel` and `drawText` would not be able to see the `colorContext` variable.
-- 3 blue is passed to col and the code section `putPixel` ... `drawText` ... to `body` via the colon syntax.
-- 4 The `putPixel` and `drawText` templates are invoked.
+- 1 `withColor` — это шаблон, который принимает на вход `col` и `body` кода.
+- 2 `colorContext` внедряется в `body`. Без аннотации `.inject` -- `putPixel` и `drawText` _не смогли бы_ увидеть переменную `colorContext` .
+- 3 `blue` передается в `col`, а раздел кода `putPixel ... drawText ...` — в `body` с помощью синтаксиса с двоеточием.
+- 4 Вызываются шаблоны `putPixel` и `drawText` .
 
-After all templates are expanded the complete example looks like:
+После раскрытия всех шаблонов полный пример выглядит так:
 
 ```nim
 let colorContext = Blue