@ -253,6 +253,8 @@ auto a = "В этой строке есть \"двойные кавычки\",
Текст умышленно перенесен на новую строку после слова `также`: строковый литерал может содержать знак перевода строки (реальное начало новой строки в исходном коде, а не комбинацию `\n`), который будет сохранен именно в этом качестве.
Текст умышленно перенесен на новую строку после слова `также`: строковый литерал может содержать знак перевода строки (реальное начало новой строки в исходном коде, а не комбинацию `\n`), который будет сохранен именно в этом качестве.
[Исходный код](src/chapter-2-2-5/)
[В начало ⮍](#2-2-5-строковые-литералы) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-2-5-строковые-литералы) [Наверх ⮍](#2-основные-типы-данных-выражения)
#### 2.2.5.1. Строковые литералы: WYSIWYG, с разделителями, строки токенов, шестнадцатеричные и импортированные
#### 2.2.5.1. Строковые литералы: WYSIWYG, с разделителями, строки токенов, шестнадцатеричные и импортированные
@ -321,6 +323,8 @@ auto x = import("resource.bin");
Строка, возвращаемая функцией `import`, не проверяется на соответствие кодировке UTF-8. Это сделано намеренно – для реализации возможности включать двоичные данные.
Строка, возвращаемая функцией `import`, не проверяется на соответствие кодировке UTF-8. Это сделано намеренно – для реализации возможности включать двоичные данные.
[Исходный код](src/chapter-2-2-5-1/)
[В начало ⮍](#2-2-5-1-строковые-литералы-wysiwyg-с-разделителями-строки-токенов-шестнадцатеричные-и-импортированные) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-2-5-1-строковые-литералы-wysiwyg-с-разделителями-строки-токенов-шестнадцатеричные-и-импортированные) [Наверх ⮍](#2-основные-типы-данных-выражения)
#### 2.2.5.2. Тип строкового литерала
#### 2.2.5.2. Тип строкового литерала
@ -404,6 +408,8 @@ dstring y = "Здравствуй, еще более широкий мир!"; //
Если вы хотите явно указать тип строки, то можете снабдить строковый литерал суффиксом: `c`, `w` или `d`, которые заставляют тип строкового литерала принять значение `string`, `wstring` или `dstring` соответственно.
Если вы хотите явно указать тип строки, то можете снабдить строковый литерал суффиксом: `c`, `w` или `d`, которые заставляют тип строкового литерала принять значение `string`, `wstring` или `dstring` соответственно.
[Исходный код](src/chapter-2-2-5-2/)
[В начало ⮍](#2-2-5-2-тип-строкового-литерала) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-2-5-2-тип-строкового-литерала) [Наверх ⮍](#2-основные-типы-данных-выражения)
### 2.2.6. Литералы массивов и ассоциативных массивов
### 2.2.6. Литералы массивов и ассоциативных массивов
Каждая ячейка литерала ассоциативного массива имеет вид `ключ: значение`. Тип ключей литерала ассоциативного массива вычисляется по массиву, в который неявно записываются все эти ключи, с помощью описанного выше способа. Тип значений вычисляется аналогично. После вычисления типа ключей `K` и типа значений `V` литерал типизируется как `V[K]`. Например, константа `famousNamedConstants` принимает тип `double[string]`.
Каждая ячейка литерала ассоциативного массива имеет вид `ключ: значение`. Тип ключей литерала ассоциативного массива вычисляется по массиву, в который неявно записываются все эти ключи, с помощью описанного выше способа. Тип значений вычисляется аналогично. После вычисления типа ключей `K` и типа значений `V` литерал типизируется как `V[K]`. Например, константа `famousNamedConstants` принимает тип `double[string]`.
[Исходный код](src/chapter-2-2-6/)
[В начало ⮍](#2-2-6-литералы-массивов-и-ассоциативных-массивов) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-2-6-литералы-массивов-и-ассоциативных-массивов) [Наверх ⮍](#2-основные-типы-данных-выражения)
### 2.2.7. Функциональные литералы
### 2.2.7. Функциональные литералы
@ -480,6 +488,8 @@ assert(b == 1.5);
Теперь тип `f`–`delegate double(int x)`. Все правила распознавания типа для `function` применимы без изменений к `delegate`. Отсюда справедливый вопрос: если конструкции `delegate` могут делать все, на что способны `function`-конструкции (в конце концов конструкции `delegate`*могут*, но *не обязаны* использовать переменные своего окружения), зачем же сначала возиться с функциями? Нельзя ли всегда использовать конструкции `delegate`? Ответ прост: все дело в эффективности. Очевидно, что конструкции `delegate` обладают доступом к большему количеству информации, а по непреложному закону природы за такой доступ приходится расплачиваться. На самом деле, размер `function` равен размеру указателя, а`delegate`– в два раза больше (один указатель на функцию, один – на окружение).
Теперь тип `f`–`delegate double(int x)`. Все правила распознавания типа для `function` применимы без изменений к `delegate`. Отсюда справедливый вопрос: если конструкции `delegate` могут делать все, на что способны `function`-конструкции (в конце концов конструкции `delegate`*могут*, но *не обязаны* использовать переменные своего окружения), зачем же сначала возиться с функциями? Нельзя ли всегда использовать конструкции `delegate`? Ответ прост: все дело в эффективности. Очевидно, что конструкции `delegate` обладают доступом к большему количеству информации, а по непреложному закону природы за такой доступ приходится расплачиваться. На самом деле, размер `function` равен размеру указателя, а`delegate`– в два раза больше (один указатель на функцию, один – на окружение).
[Исходный код](src/chapter-2-2-7/)
[В начало ⮍](#2-2-7-функциональные-литералы) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-2-7-функциональные-литералы) [Наверх ⮍](#2-основные-типы-данных-выражения)
## 2.3. Операции
## 2.3. Операции
@ -711,6 +721,8 @@ bool
|`shared`|`Тип`|
|`shared`|`Тип`|
|`return`|Тип, возвращаемый функцией, оператором `delegate` или указателем на функцию|
|`return`|Тип, возвращаемый функцией, оператором `delegate` или указателем на функцию|
[Исходный код](src/chapter-2-3-4-3/)
[В начало ⮍](#2-3-4-3-выражения-is) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-4-3-выражения-is) [Наверх ⮍](#2-основные-типы-данных-выражения)
#### 2.3.4.4. Выражения в круглых скобках
#### 2.3.4.4. Выражения в круглых скобках
@ -759,6 +771,8 @@ assert(a == [ 0, 0, 0, 1, 3 ]); // a был изменен
Если `i > j` или `j > a.length`, генерируется исключение типа `RangeError`. Иначе если `i == j`, будет возвращен пустой массив. В качестве `arr` в выражении `arr[i .. j]` можно использовать указатель. В этом случае будет возвращен массив, отражающий область памяти начиная с адреса `arr + i` до `arr + j` (не включая элемент с адресом `arr + j`). Если `i > j`, генерируется ошибка `RangeError`, иначе при получении среза указателя границы не проверяются. И снова в некоторых режимах сборки (небезопасные итоговые сборки, см. раздел 4.1.2) все проверки границ при получении срезов могут быть отключены.
Если `i > j` или `j > a.length`, генерируется исключение типа `RangeError`. Иначе если `i == j`, будет возвращен пустой массив. В качестве `arr` в выражении `arr[i .. j]` можно использовать указатель. В этом случае будет возвращен массив, отражающий область памяти начиная с адреса `arr + i` до `arr + j` (не включая элемент с адресом `arr + j`). Если `i > j`, генерируется ошибка `RangeError`, иначе при получении среза указателя границы не проверяются. И снова в некоторых режимах сборки (небезопасные итоговые сборки, см. раздел 4.1.2) все проверки границ при получении срезов могут быть отключены.
[Исходный код](src/chapter-2-3-5-5/)
[В начало ⮍](#2-3-5-5-срезы-массивов) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-5-5-срезы-массивов) [Наверх ⮍](#2-основные-типы-данных-выражения)
#### 2.3.5.6. Создание вложенного класса
#### 2.3.5.6. Создание вложенного класса
@ -820,6 +834,8 @@ foreach (ref row; matrix)
Необязательный `адрес`, расположенный сразу после ключевого слова `new`, вводит конструкцию, называемую *новым размещением*. По смыслу вариант `new(адрес) T` отличается от других: вместо выделения памяти под новый объект происходит размещение объекта по заданному `адресу`. Такие низкоуровневые средства в обычном коде не применяются. Вы можете использовать их, например, чтобы распределять память из кучи C с помощью `malloc` и затем использовать ее для хранения значений языка D.
Необязательный `адрес`, расположенный сразу после ключевого слова `new`, вводит конструкцию, называемую *новым размещением*. По смыслу вариант `new(адрес) T` отличается от других: вместо выделения памяти под новый объект происходит размещение объекта по заданному `адресу`. Такие низкоуровневые средства в обычном коде не применяются. Вы можете использовать их, например, чтобы распределять память из кучи C с помощью `malloc` и затем использовать ее для хранения значений языка D.
[Исходный код](src/chapter-2-3-6-1/)
[В начало ⮍](#2-3-6-1-выражение-new) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-6-1-выражение-new) [Наверх ⮍](#2-основные-типы-данных-выражения)
#### 2.3.6.2. Получение адреса и разыменование
#### 2.3.6.2. Получение адреса и разыменование
@ -882,6 +898,8 @@ foreach (ref row; matrix)
Результат возведения нуля в нулевую степень – единица, а в любую другую – ноль.
Результат возведения нуля в нулевую степень – единица, а в любую другую – ноль.
[Исходный код](src/chapter-2-3-7/)
[В начало ⮍](#2-3-7-возведение-в-степень) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-7-возведение-в-степень) [Наверх ⮍](#2-основные-типы-данных-выражения)
### 2.3.8. Мультипликативные операции
### 2.3.8. Мультипликативные операции
@ -898,6 +916,8 @@ foreach (ref row; matrix)
Если такое число найти невозможно, результатом `a % b` будет особое значение NaN.
Если такое число найти невозможно, результатом `a % b` будет особое значение NaN.
[Исходный код](src/chapter-2-3-8/)
[В начало ⮍](#2-3-8-мультипликативные-операции) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-8-мультипликативные-операции) [Наверх ⮍](#2-основные-типы-данных-выражения)
### 2.3.9. Аддитивные операции
### 2.3.9. Аддитивные операции
@ -950,6 +970,8 @@ auto d = a >> b; // Результат зависит от реализации
Раньше было популярно с помощью операции сдвига реализовывать быстрое целочисленное умножение на 2 (`a <<1`)илиделениена2(`a>> 1`) – или в общем случае умножение и деление на различные степени 2. Эта техника вышла из употребления, подобно видеокассетам. Пишите просто: `a * k` или `a / k`; если значение `k` известно на этапе компиляции, компилятор гарантированно сгенерирует для вас оптимальный код с операциями сдвига и всем, что еще нужно, избавив вас от волнений по поводу тонкостей работы со знаком. Не ищите сдвига на свою голову.
Раньше было популярно с помощью операции сдвига реализовывать быстрое целочисленное умножение на 2 (`a <<1`)илиделениена2(`a>> 1`) – или в общем случае умножение и деление на различные степени 2. Эта техника вышла из употребления, подобно видеокассетам. Пишите просто: `a * k` или `a / k`; если значение `k` известно на этапе компиляции, компилятор гарантированно сгенерирует для вас оптимальный код с операциями сдвига и всем, что еще нужно, избавив вас от волнений по поводу тонкостей работы со знаком. Не ищите сдвига на свою голову.
[Исходный код](src/chapter-2-3-10/)
[В начало ⮍](#2-3-10-сдвиг) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-10-сдвиг) [Наверх ⮍](#2-основные-типы-данных-выражения)
### 2.3.11. Выражения in
### 2.3.11. Выражения in
@ -989,6 +1011,8 @@ else
}
}
```
```
[Исходный код](src/chapter-2-3-11/)
[В начало ⮍](#2-3-11-выражения-in) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-11-выражения-in) [Наверх ⮍](#2-основные-типы-данных-выражения)
### 2.3.12. Сравнение
### 2.3.12. Сравнение
@ -1029,6 +1053,8 @@ void main()
Вместо выражения проверки на неравенство `!(a is b)` можно использовать его краткий вариант `a !is b`.
Вместо выражения проверки на неравенство `!(a is b)` можно использовать его краткий вариант `a !is b`.
[Исходный код](src/chapter-2-3-12-1/)
[В начало ⮍](#2-3-12-1-проверка-на-равенство) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-12-1-проверка-на-равенство) [Наверх ⮍](#2-основные-типы-данных-выражения)
#### 2.3.12.2. Сравнение для упорядочивания
#### 2.3.12.2. Сравнение для упорядочивания
@ -1072,6 +1098,8 @@ string line;
line == "#\n" && writeln("Успешно принята строка #. ");
line == "#\n" && writeln("Успешно принята строка #. ");
```
```
[Исходный код](src/chapter-2-3-14/)
[В начало ⮍](#2-3-14-логическое-и) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-14-логическое-и) [Наверх ⮍](#2-основные-типы-данных-выражения)
### 2.3.15. Логическое ИЛИ
### 2.3.15. Логическое ИЛИ
@ -1089,6 +1117,8 @@ string line;
line.length > 0 || line = "\n";
line.length > 0 || line = "\n";
```
```
[Исходный код](src/chapter-2-3-15/)
[В начало ⮍](#2-3-15-логическое-или) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-15-логическое-или) [Наверх ⮍](#2-основные-типы-данных-выражения)
### 2.3.16. Тернарная условная операция
### 2.3.16. Тернарная условная операция
@ -1114,6 +1144,8 @@ assert(x == 10);
Многие концептуальные примеры обобщенного программирования используют тернарную операцию сравнения для нахождения общего типа двух значений.
Многие концептуальные примеры обобщенного программирования используют тернарную операцию сравнения для нахождения общего типа двух значений.
[Исходный код](src/chapter-2-3-16/)
[В начало ⮍](#2-3-16-тернарная-условная-операция) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-16-тернарная-условная-операция) [Наверх ⮍](#2-основные-типы-данных-выражения)
### 2.3.17. Присваивание
### 2.3.17. Присваивание
@ -1138,6 +1170,8 @@ int c = (a = b, b = 7, 8);
После выполнения этого фрагмента кода переменные `a`, `b` и `c` примут значения `10`, `7` и `8` соответственно.
После выполнения этого фрагмента кода переменные `a`, `b` и `c` примут значения `10`, `7` и `8` соответственно.
[Исходный код](src/chapter-2-3-18/)
[В начало ⮍](#2-3-18-выражения-с-запятой) [Наверх ⮍](#2-основные-типы-данных-выражения)
[В начало ⮍](#2-3-18-выражения-с-запятой) [Наверх ⮍](#2-основные-типы-данных-выражения)
## 2.4. Итоги и справочник
## 2.4. Итоги и справочник
@ -1170,7 +1204,7 @@ int c = (a = b, b = 7, 8);
|`a.b`|Доступ к вложенным элементам ([см. раздел 2.3.5.1](#2-3-5-1-доступ-ко-внутренним-элементам))|
|`a.b`|Доступ к вложенным элементам ([см. раздел 2.3.5.1](#2-3-5-1-доступ-ко-внутренним-элементам))|
|`a++`|Постфиксный вариа нт операции увеличения на единицу ([см. раздел 2.3.5.2](#2-3-5-2-увеличение-и-уменьшение-на-единицу))|
|`a++`|Постфиксный вариа нт операции увеличения на единицу ([см. раздел 2.3.5.2](#2-3-5-2-увеличение-и-уменьшение-на-единицу))|
|`a--`|Постфиксный вариант операции уменьшения на единицу ([см. раздел 2.3.5.2](#2-3-5-2-увеличение-и-уменьшение-на-единицу))|
|`a--`|Постфиксный вариант операции уменьшения на единицу ([см. раздел 2.3.5.2](#2-3-5-2-увеличение-и-уменьшение-на-единицу))|
|`a(<арг>)`|Оператор вызова функции (`<арг> = ` необязательный список аргументов, разделенных запятыми) ([см. раздел 2.3.5.3](#2-3-5-3-вызов-функции))|
|`a(<арг>опционально)`|Оператор вызова функции (`<арг>опционально = ` необязательный список аргументов, разделенных запятыми) ([см. раздел 2.3.5.3](#2-3-5-3-вызов-функции))|
|`a[<арг>]`|Оператор индексации (`<арг> = ` список аргументов, разделенных запятыми) ([см. раздел 2.3.5.4](#2-3-5-4-индексация))|
|`a[<арг>]`|Оператор индексации (`<арг> = ` список аргументов, разделенных запятыми) ([см. раздел 2.3.5.4](#2-3-5-4-индексация))|
|`a[]`|Срез в размере всего массива ([см. раздел 2.3.5.5](#2-3-5-5-срезы-массивов))|
|`a[]`|Срез в размере всего массива ([см. раздел 2.3.5.5](#2-3-5-5-срезы-массивов))|
|`a[b .. c]`|Срез ([см. раздел 2.3.5.5](#2-3-5-5-срезы-массивов))|
|`a[b .. c]`|Срез ([см. раздел 2.3.5.5](#2-3-5-5-срезы-массивов))|