Browse Source

SVI Add ch08

SVI 1 month ago
parent
commit
a7f9aac3e4
1 changed files with 33 additions and 42 deletions
  1. 33 42
      doc/part01/ch08.md

+ 33 - 42
doc/part01/ch08.md

@@ -1,8 +1,8 @@
-# Chapter 8. Generics
+# Глава 8. Обобщения
 
-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.
+Итератор `items`, который только что был рассмотрен, работает только с `seq[Point]`. Однако в коде не используются никакие возможности `Point`, например он не обращается к `point.x`. Бывает нужно перебрать все `seq[T]`, где `T` может быть любого типа.
 
-**Nim** supports such type variables via generics:
+**Nim** поддерживает такие переменные типов с помощью _обобщений_:
 
 ```nim
 iterator items[T](s: seq[T]): T =             # 1
@@ -12,35 +12,31 @@ iterator items[T](s: seq[T]): T =             # 1
     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.
+- 1 Итератор `items` работает с любым типом `seq[T]`. Он возвращает значения типа `T`.
+- 2 `@[1, 2, 3]` имеет тип `seq[int]`. При вызове `items` его переменная типа `T` определяется как `int`.
+- 3 `@["1", "2", "3"]` имеет тип `seq[string]`. При вызове `items` его переменная типа `T` определяется как `string`.
 
-**Nim** uses specialization for its generics. Every new concrete type like `int` or
-`string` produces specialized code, there is no runtime overhead.
+**Nim** использует специализацию для обобщений. Каждый новый конкретный тип, такой как `int` или `string`, генерирует специализированный код, что не требует дополнительных затрат во время выполнения.
 
-Not only `procs` and iterators but also types can be generic:
+Обобщенными могут быть не только `procs` и итераторы, но и типы:
 
 ```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
+    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`.
+- 1 Тип `Point` параметризуется переменной типа `T`.
+- 2 `T` используется для объявления полей `x` и `y`.
+- 3 Объявлена переменная с именем `p`, имеющая тип `Point[float]`
+- 4 Для создания объекта `Point` также требуется явный тип; в данном случае `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.
+К сожалению, вывод типов не работает при создании объектов, `Point(x: 1.0, y: 3.0)` не допускается без параметризации явным типом. Вероятно, в будущем это ограничение будет снято.
 
-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:
+Если тип параметризован переменной типа `T`, то операции с ним обычно тоже должны быть параметризованы. Например, процедура `drawHorizontalLine` стала бы такой:
 
 ```nim
 proc drawHorizontalLine[T](a, b: Point[T]) =
@@ -51,16 +47,14 @@ proc drawHorizontalLine[T](a, b: Point[T]) =
          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.
+`drawHorizontalLine` принимает два параметра одного типа `Point[T]`. Другими словами, вызов вида `drawHorizontalLine(Point[float](x: 2.0, y: 3.0), Point[int](x: 2, y: 3))` будет отклонен, потому что один `T` не может быть одновременно `float` и `int`.
+
+Мы можем использовать переменные разных типов, чтобы обеспечить работу с несколькими параметрическими типами одновременно
 
-We can use different type variables to allow for
+`drawHorizontalLine(Point[float](x: 2.0, y: 3.0), Point[int](x: 2, y: 3))`:
 
 ```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]) =
+proc drawHorizontalLine[T, U](a: Point[T]; b: Point[U]) =
     if b.x < a.x:
        drawHorizontalLine(b, a)
     else:
@@ -68,8 +62,7 @@ drawHorizontalLine(Point[float](x: 2.0, y: 3.0), Point[int](x: 2, y: 3)):
          putPixel(x, a.y)
 ```
 
-This assumes that we have an iterator `..` that can handle mixed types. We
-could provide such an iterator like this:
+то предполагает, что у нас есть итератор `..`, который может работать со смешанными типами. Например, можно реализовать такой итератор следующим образом:
 
 ```nim
 iterator `..`[T, U](a: T, b: U): U = # 1
@@ -79,17 +72,15 @@ iterator `..`[T, U](a: T, b: U): U = # 1
       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`.
+- 1 несколько произвольно решено, что создаваемые значения относятся к типу `U`, а не к `T`.
+- 2 С помощью `U(a)` мы преобразуем исходное значение `a` в тип `U`. В **Nim** преобразование типа выглядит как вызов функции.
+- 3 Здесь делается предположение, что тип `U` предлагает оператор `<=`. Это предположение не зафиксировано — обобщения в **Nim** могут быть недостаточно конкретными.
+4 Здесь предположено, что тип `U` поддерживает подходящую операцию `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:
+Переменная типа `T` обычно не указывается в **Nim**; требования являются только неявными, и тип универсального кода проверяется только при создании экземпляра универсального кода:
 
 ```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`
+for x in "a".."b": ... # неправильно
+for x in 0 .. 3: ...   # правильно
+for x in 0 .. 3.0: ... # неправильные типы: `float` не является `inc`
 ```