SVI 1 ماه پیش
والد
کامیت
2f40f542c3
2فایلهای تغییر یافته به همراه75 افزوده شده و 55 حذف شده
  1. 74 55
      doc/part01/ch08.md
  2. 1 0
      doc/part01/main.md

+ 74 - 55
doc/part01/ch08.md

@@ -1,51 +1,64 @@
 # Chapter 8. Generics
 
-The items iterator that we have just seen only works on seq[Point]. However,
-the code does not use any features of Point, it doesn’t access point.x, for
-example. We really want to iterate over every seq[T] where T can be any
-type.
-Nim supports such type variables via generics:
-  iterator items[T](s: seq[T]): T = 1
+The items iterator that we have just seen only works on `seq[Point]`. However, the code does not use any features of `Point`, it doesn’t access `point.x`, for example. We really want to iterate over every `seq[T]` where `T` can be any type.
+
+**Nim** supports such type variables via generics:
+
+```nim
+iterator items[T](s: seq[T]): T =             # 1
     for i in 0 ..< s.len:
-      yield s[i]
-  for x in items(@[1, 2, 3]): discard 2
-  for x in items(@["1", "2", "3"]): discard 3
- 1 The items iterator works for any type seq[T]. It produces values of type T.
- 2 @[1, 2, 3] has type seq[int]. When items is called its type variable T is
-    inferred to be int.
- 3 @["1", "2", "3"] has type seq[string]. When items is called its type
-    variable T is inferred to be string.
-Nim uses specialization for its generics. Every new concrete type like int or
-string produces specialized code, there is no runtime overhead.
-Not only procs and iterators but also types can be generic:
-  type
-    Point[T] = object 1
-       x, y: T 2
-  var p: Point[float] 3
-  p = Point[float](x: 1.0, y: 3.0) 4
-                                                                            35
- 1 The Point type is parametrized by a type variable T.
- 2 T is used to declare the fields x and y.
- 3 A variable of name p is declared that is of type Point[float]
- 4 Object construction of Point also requires an explicit type; in this case
-     float.
-Unfortunately type inference does not work for object construction, Point(x:
-1.0, y: 3.0) is not allowed. This restriction will probably be removed in the
+        yield s[i]
+    for x in items(@[1, 2, 3]): discard       # 2
+    for x in items(@["1", "2", "3"]): discard # 3
+```
+
+- 1 The items iterator works for any type `seq[T]`. It produces values of type `T`.
+- 2 `@[1, 2, 3]` has type `seq[int]`. When items is called its type variable `T` is inferred to be `int`.
+- 3 `@["1", "2", "3"]` has type `seq[string]`. When items is called its type variable `T` is inferred to be string.
+
+**Nim** uses specialization for its generics. Every new concrete type like `int` or
+`string` produces specialized code, there is no runtime overhead.
+
+Not only `procs` and iterators but also types can be generic:
+
+```nim
+type
+    Point[T] = object              # 1
+       x, y: T                     # 2
+  var p: Point[float]              # 3
+  p = Point[float](x: 1.0, y: 3.0) # 4
+```
+
+- 1 The `Point` type is parametrized by a type variable `T`.
+- 2 `T` is used to declare the fields `x` and `y`.
+- 3 A variable of name `p` is declared that is of type `Point[float]`
+- 4 Object construction of `Point` also requires an explicit type; in this case `float`.
+
+Unfortunately type inference does not work for object construction, `Point(x:
+1.0, y: 3.0)` is not allowed. This restriction will probably be removed in the
 future.
-If a type is parametrized by a type variable T operations on it usually have to
-be parametrized too. For example, our drawHorizontalLine proc would
+
+If a type is parametrized by a type variable `T` operations on it usually have to
+be parametrized too. For example, our `drawHorizontalLine` proc would
 become:
-  proc drawHorizontalLine[T](a, b: Point[T]) =
+
+```nim
+proc drawHorizontalLine[T](a, b: Point[T]) =
     if b.x < a.x:
        drawHorizontalLine(b, a)
     else:
        for x in a.x .. b.x:
          putPixel(x, a.y)
-drawHorizontalLine takes two parameters of the same type Point[T]. In other
-words, a call like drawHorizontalLine(Point[float](x:          2.0,  y:   3.0),
-Point[int](x: 2, y: 3)) would be rejected because one T cannot be both
-float and int at the same time.
-We       can     use      different   type     variables    to    allow     for
+```
+
+`drawHorizontalLine` takes two parameters of the same type `Point[T]`. In other
+words, a call like `drawHorizontalLine(Point[float](x: 2.0, y: 3.0),
+Point[int](x: 2, y: 3))` would be rejected because one `T` cannot be both
+`float` and `int` at the same time.
+
+We can use different type variables to allow for
+
+```nim
 drawHorizontalLine(Point[float](x: 2.0, y: 3.0), Point[int](x: 2, y: 3)):
   proc drawHorizontalLine[T, U](a: Point[T]; b: Point[U]) =
     if b.x < a.x:
@@ -53,24 +66,30 @@ drawHorizontalLine(Point[float](x: 2.0, y: 3.0), Point[int](x: 2, y: 3)):
     else:
        for x in a.x .. b.x:
          putPixel(x, a.y)
-This assumes that we have an iterator .. that can handle mixed types. We
+```
+
+This assumes that we have an iterator `..` that can handle mixed types. We
 could provide such an iterator like this:
-36
-  iterator `..`[T, U](a: T, b: U): U = 1
-    var i = U(a) 2
-    while i <= b: 3
+
+```nim
+iterator `..`[T, U](a: T, b: U): U = # 1
+    var i = U(a)                     # 2
+    while i <= b:                    # 3
       yield i
-      inc i   4
- 1 Somewhat arbitrarily we have decided that the produced values are of
-    type U and not of T.
- 2 Via U(a) we convert the starting value a to type U. In Nim a type
-    conversion looks like a function call.
- 3 We assume here that type U offers an operator <=. This assumption is not
-    written down — generics in Nim can be under-specified.
- 4 We assume here that type U offers a suitable operation inc.
-A type variable T is usually left under-specified in Nim; the requirements are
+      inc i                          # 4
+```
+
+- 1 Somewhat arbitrarily we have decided that the produced values are of type `U` and not of `T`.
+- 2 Via `U(a)` we convert the starting value a to type `U`. In **Nim** a type conversion looks like a function call.
+- 3 We assume here that type `U` offers an operator `<=`. This assumption is not written down — generics in **Nim** can be under-specified.
+- 4 We assume here that type `U` offers a suitable operation `inc`.
+
+A type variable `T` is usually left under-specified in **Nim**; the requirements are
 only implicit and generic code is only type checked when the generic is
 instantiated:
-  for x in "a".."b": ... # invalid
-  for x in 0 .. 3: ... # valid
-  for x in 0 .. 3.0: ... # invalid because float does not have `inc`
+
+```nim
+for x in "a".."b": ... # invalid
+for x in 0 .. 3: ...   # valid
+for x in 0 .. 3.0: ... # invalid because float does not have `inc`
+```

+ 1 - 0
doc/part01/main.md

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