SVI před 1 měsícem
rodič
revize
00ce91d43d
2 změnil soubory, kde provedl 96 přidání a 92 odebrání
  1. 95 92
      doc/part01/ch09.md
  2. 1 0
      doc/part01/main.md

+ 95 - 92
doc/part01/ch09.md

@@ -1,113 +1,116 @@
-# Chapter 9. Templates
-
-What happens when we call putPixel on coordinates that lie outside the
-screen’s boundaries? That depends on the implementation of our pixels
-library but three outcomes are conceivable:
-  1. Nothing.
-  2. An exception is raised.
-  3. The program crashes.
+# Глава 9. Шаблоны
+
+Что происходит, когда мы вызываем `putPixel` для координат, выходящих за границы экрана? Это зависит от реализации нашей библиотеки пикселей, но возможны три варианта:
+
+- 1 Ничего.
+- 2 Возникает исключение.
+- 3 Программа выходит из строя.
+
 In order to do “nothing” early returns can be a handy mechanism:
-  const
-    ScreenWidth = 1024 1
+
+```nim
+const
+    ScreenWidth = 1024 # 1
     ScreenHeight = 768
-  proc safePutPixel(x, y: int; col: Color) =
+
+proc safePutPixel(x, y: int; col: Color) =
     if x < 0 or x >= ScreenWidth or
         y < 0 or y >= ScreenHeight:
-       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.
-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.
-Unfortunately, a return statement leaves the current proc and so code like the
-following has not the desired effect:
-                                                                            39
+       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.
+
+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.
+
+Unfortunately, a return statement leaves the current proc and so code like the following has not the desired effect:
+
+```nim
   proc boundsCheck(x, y: int) =
     if x < 0 or x >= ScreenWidth or
        y < 0 or y >= ScreenHeight:
-      return 1
+      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!
-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:
-  template boundsCheck(a, b: int) = 1
+```
+
+- 1 The return statements leaves boundsCheck but not 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
+template boundsCheck(a, b: int) = # 1
     if a < 0 or a >= ScreenWidth or
        b < 0 or b >= ScreenHeight:
-      return 2
-  proc safePutPixel(x, y: int; col: Color) =
-    boundsCheck(x, y) 3
+      return # 2
+proc safePutPixel(x, y: int; col: Color) =
+    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.
-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.
-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:
-40
- template wrap(body: untyped) = 1
-    drawText 0, 10, "Before Body", 8, Yellow 2
-    body 3
- wrap: 4
+```
+
+- 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.
+
+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.
+
+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
+    drawText 0, 10, "Before Body", 8, Yellow # 2
+    body                                     # 3
+wrap:                                        # 4
     for i in 1..3:
       let textToDraw = "Welcome to Nim for the " & $i & "th time!"
       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.
-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:
- 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.
-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
-compiler performs a mechanism that is called overload resolution in order to
-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
-                                                                              41
-this name. The same applies for drawText.
+```
+
+- 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.
+
+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:
+
+```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`.
+
+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.
-The colorContext variable is declared inside the withColor environment. It is
-marked with inject so that it is visible inside the body:
- template withColor(col: Color; body: untyped) = 1
-    let colorContext {.inject.} = col 2
+
+The `colorContext` variable is declared inside the withColor environment. It is marked with inject so that it is visible inside the body:
+
+```nim
+template withColor(col: Color; body: untyped) = # 1
+    let colorContext {.inject.} = col           # 2
     body
- withColor Blue: 3
-    putPixel 3, 4 4
+withColor Blue:                                 # 3
+    putPixel 3, 4                               # 4
     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` 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.
+
 After all templates are expanded the complete example looks like:
- let colorContext = Blue
- putPixel(3, 4, colorContext)
- drawText(10, 10, "abc", colorContext)
+
+```nim
+let colorContext = Blue
+putPixel(3, 4, colorContext)
+drawText(10, 10, "abc", colorContext)
+```

+ 1 - 0
doc/part01/main.md

@@ -8,3 +8,4 @@
 - [Глава 6](./ch06.md)
 - [Глава 7](./ch07.md)
 - [Глава 8](./ch08.md)
+- [Глава 9](./ch09.md)