Глава 4 закончена

This commit is contained in:
Alexander Zhirov 2023-02-25 17:15:12 +03:00
parent 141dd624b1
commit e57718386b
26 changed files with 442 additions and 2 deletions

View File

@ -125,6 +125,8 @@ assert(a !is null);
Благодаря последней строке этого кода обнаруживается нечто странное: пустой массив это необязательно `null`. Благодаря последней строке этого кода обнаруживается нечто странное: пустой массив это необязательно `null`.
[Исходный код](src/chapter-4-1/)
[В начало ⮍](#4-1-динамические-массивы) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-динамические-массивы) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.1.1. Длина ### 4.1.1. Длина
@ -146,6 +148,8 @@ assert(array[$ - 1] == 42);
Изменение длины массива обсуждается в разделах 4.1.84.1.10. Изменение длины массива обсуждается в разделах 4.1.84.1.10.
[Исходный код](src/chapter-4-1-1/)
[В начало ⮍](#4-1-1-длина) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-1-длина) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.1.2. Проверка границ ### 4.1.2. Проверка границ
@ -235,6 +239,8 @@ array = array[$ / 2 .. $];
Выражение `array[0 .. $]` получает срез, включающий все содержимое массива `array`. Это выражение встречается довольно часто, и тут язык помогает программистам, позволяя вместо записи `array[0 .. $]` использовать краткую форму `array[]`. Выражение `array[0 .. $]` получает срез, включающий все содержимое массива `array`. Это выражение встречается довольно часто, и тут язык помогает программистам, позволяя вместо записи `array[0 .. $]` использовать краткую форму `array[]`.
[Исходный код](src/chapter-4-1-3/)
[В начало ⮍](#4-1-3-срезы) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-3-срезы) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.1.4. Копирование ### 4.1.4. Копирование
@ -281,6 +287,8 @@ subarray[1] = 33;
assert(array[2] == 33); // Изменение массива subarray отразилось на массиве array assert(array[2] == 33); // Изменение массива subarray отразилось на массиве array
``` ```
[Исходный код](src/chapter-4-1-4/)
[В начало ⮍](#4-1-4-копирование) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-4-копирование) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.1.5. Проверка на равенство ### 4.1.5. Проверка на равенство
@ -301,6 +309,8 @@ assert(a !is b); // Тест пройден, a и b различны, хотя
При поэлементном сравнении массивов просматриваются все элементы обоих массивов и соответствующие пары сравниваются по очереди с помощью оператора `==`. При поэлементном сравнении массивов просматриваются все элементы обоих массивов и соответствующие пары сравниваются по очереди с помощью оператора `==`.
[Исходный код](src/chapter-4-1-5/)
[В начало ⮍](#4-1-5-проверка-на-равенство) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-5-проверка-на-равенство) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.1.6. Конкатенация ### 4.1.6. Конкатенация
@ -323,6 +333,8 @@ assert(a.length == 8);
Под результирующий массив всегда выделяется новая область памяти. Под результирующий массив всегда выделяется новая область памяти.
[Исходный код](src/chapter-4-1-6/)
[В начало ⮍](#4-1-6-конкатенация) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-6-конкатенация) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.1.7. Поэлементные операции ### 4.1.7. Поэлементные операции
@ -385,6 +397,8 @@ a[] = b[]; // Скопировать все данные из b в a
Поэлементные операции очень мощны, а чем больше мощность, тем больше ответственность. Именно вы отвечаете за отсутствие перекрывания между l- и r-значениями каждого присваивания в поэлементной операции. Приводя высокоуровневые операции к примитивным операциям над векторами, которые может выполнять конечный процессор (на котором будет исполняться программа), компилятор вправе считать, что это именно так. Если вы намеренно используете перекрывание, то напишите циклы обработки элементов массива вручную, чтобы компилятор не смог выполнить какие-то непроверенные присваивания. Поэлементные операции очень мощны, а чем больше мощность, тем больше ответственность. Именно вы отвечаете за отсутствие перекрывания между l- и r-значениями каждого присваивания в поэлементной операции. Приводя высокоуровневые операции к примитивным операциям над векторами, которые может выполнять конечный процессор (на котором будет исполняться программа), компилятор вправе считать, что это именно так. Если вы намеренно используете перекрывание, то напишите циклы обработки элементов массива вручную, чтобы компилятор не смог выполнить какие-то непроверенные присваивания.
[Исходный код](src/chapter-4-1-7/)
[В начало ⮍](#4-1-7-поэлементные-операции) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-7-поэлементные-операции) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.1.8. Сужение ### 4.1.8. Сужение
@ -436,6 +450,8 @@ palindrome 34 95 548
то содержимое массива `args` примет вид `["palindrome", "34", "95", "548"]`. Вот где пригодилось сужение слева `args = args[1 .. $]`: оно сокращает массив args до массива `["34", "95", "548"]`. Затем программа пошагово сравнивает элементы на концах массива. Если они не равны, то дальше можно не сравнивать: пишем `"не палиндром"` и закругляемся. А если проверка прошла успешно, то сужаем массив `args` с обоих концов. Только если все проверки возвратят `true`, а в массиве `args` останется не больше одного элемента (пустые массивы и массивы из одного элемента программа считает палиндромами), программа напечатает `"палиндром"` и завершится. Несмотря на то что программа активно манипулирует массивами, после инициализации массива `args` память не перераспределялась ни разу. Работа начинается c обращения к массиву `args` (память под который была выделена заранее), а потом он только сужается. то содержимое массива `args` примет вид `["palindrome", "34", "95", "548"]`. Вот где пригодилось сужение слева `args = args[1 .. $]`: оно сокращает массив args до массива `["34", "95", "548"]`. Затем программа пошагово сравнивает элементы на концах массива. Если они не равны, то дальше можно не сравнивать: пишем `"не палиндром"` и закругляемся. А если проверка прошла успешно, то сужаем массив `args` с обоих концов. Только если все проверки возвратят `true`, а в массиве `args` останется не больше одного элемента (пустые массивы и массивы из одного элемента программа считает палиндромами), программа напечатает `"палиндром"` и завершится. Несмотря на то что программа активно манипулирует массивами, после инициализации массива `args` память не перераспределялась ни разу. Работа начинается c обращения к массиву `args` (память под который была выделена заранее), а потом он только сужается.
[Исходный код](src/chapter-4-1-8/)
[В начало ⮍](#4-1-8-сужение) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-8-сужение) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.1.9. Расширение ### 4.1.9. Расширение
@ -500,6 +516,8 @@ assert(b == [40, 50, 60, 70]); // Тест пройден; массив a был
Этот код искусно заставляет массив `a` думать, что в конце области памяти, которую он занимает, есть свободное место: первоначально массив `a` был больше по размеру, затем массив `b` занял вторую половину массива `a`, а сам массив `a` сузился до своей первой половины. Перед добавлением новых элементов в массив `a` массивы `a` и `b` занимали соседние области памяти: массив `a` находился слева от массива `b`. Однако успешное выполнение теста `assert` после добавления новых элементов в массив a подтвердило, что этот массив был перенесен в другую область памяти, а не расширился на том же месте. Оператор расширения добавляет в массив элементы без изменения адреса массива, только если уверен, что справа от расширяющегося массива нет другого массива, и при малейшем сомнении всегда готов подстраховаться, перераспределив память. Этот код искусно заставляет массив `a` думать, что в конце области памяти, которую он занимает, есть свободное место: первоначально массив `a` был больше по размеру, затем массив `b` занял вторую половину массива `a`, а сам массив `a` сузился до своей первой половины. Перед добавлением новых элементов в массив `a` массивы `a` и `b` занимали соседние области памяти: массив `a` находился слева от массива `b`. Однако успешное выполнение теста `assert` после добавления новых элементов в массив a подтвердило, что этот массив был перенесен в другую область памяти, а не расширился на том же месте. Оператор расширения добавляет в массив элементы без изменения адреса массива, только если уверен, что справа от расширяющегося массива нет другого массива, и при малейшем сомнении всегда готов подстраховаться, перераспределив память.
[Исходный код](src/chapter-4-1-9/)
[В начало ⮍](#4-1-9-расширение) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-9-расширение) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.1.10. Присваивание значения свойству .length ### 4.1.10. Присваивание значения свойству .length
@ -531,6 +549,8 @@ assert(array.length == 101);
Здесь нет никакой магии; все, что необходимо сделать компилятору, это переписать выражение `array.length о= b` в несколько иной форме: `array.length = array.length о b`. И все-таки немного магии тут есть (на самом деле, всего лишь ловкость рук): в переписанном выражении массив вычисляется всего лишь раз, что очень кстати, если реально `array` это какое-то замысловатое выражение. Здесь нет никакой магии; все, что необходимо сделать компилятору, это переписать выражение `array.length о= b` в несколько иной форме: `array.length = array.length о b`. И все-таки немного магии тут есть (на самом деле, всего лишь ловкость рук): в переписанном выражении массив вычисляется всего лишь раз, что очень кстати, если реально `array` это какое-то замысловатое выражение.
[Исходный код](src/chapter-4-1-10/)
[В начало ⮍](#4-1-10-присваивание-значения-свойству-length) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-1-10-присваивание-значения-свойству-length) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
## 4.2. Массивы фиксированной длины ## 4.2. Массивы фиксированной длины
@ -598,6 +618,7 @@ foreach (ref element; array)
element = uniform(0.0, 1.0); element = uniform(0.0, 1.0);
} }
``` ```
[Исходный код](src/chapter-4-2/)
[В начало ⮍](#4-2-массивы-фиксированной-длины) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-2-массивы-фиксированной-длины) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
@ -649,6 +670,7 @@ int[] b = a[1 .. 7]; // Все в порядке
auto c = a[1 .. 7]; // Все в порядке, c также имеет тип int[] auto c = a[1 .. 7]; // Все в порядке, c также имеет тип int[]
int[6] d = a[1 .. 7]; // Все в порядке, срез a[1 .. 7] скопирован в d int[6] d = a[1 .. 7]; // Все в порядке, срез a[1 .. 7] скопирован в d
``` ```
[Исходный код](src/chapter-4-2-3/)
[В начало ⮍](#4-2-3-получение-срезов) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-2-3-получение-срезов) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
@ -690,6 +712,8 @@ auto r = fun(point); // Все в порядке, теперь r имеет
Свойство `.dup` позволяет получить дубликат массива фиксированной длины (см. раздел 4.1), но вы получите не объект типа `T[n]`, а динамически выделенный массив типа `T[]`, содержащий копию массива фиксированной длины. Такое поведение оправданно, ведь чтобы получить копию статического массива `а` того же типа, не нужно прибегать ни к каким дополнительным ухищрениям просто напишите `auto copy = a`. Свойство `.dup` позволяет получить дубликат массива фиксированной длины (см. раздел 4.1), но вы получите не объект типа `T[n]`, а динамически выделенный массив типа `T[]`, содержащий копию массива фиксированной длины. Такое поведение оправданно, ведь чтобы получить копию статического массива `а` того же типа, не нужно прибегать ни к каким дополнительным ухищрениям просто напишите `auto copy = a`.
[Исходный код](src/chapter-4-2-4/)
[В начало ⮍](#4-2-4-копирование-и-неявные-преобразования) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-2-4-копирование-и-неявные-преобразования) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.2.5. Проверка на равенство ### 4.2.5. Проверка на равенство
@ -709,6 +733,8 @@ assert(dynamic !is fixed);
assert(dynamic == fixed); assert(dynamic == fixed);
``` ```
[Исходный код](src/chapter-4-2-5/)
[В начало ⮍](#4-2-5-проверка-на-равенство) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-2-5-проверка-на-равенство) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.2.6. Конкатенация ### 4.2.6. Конкатенация
@ -726,6 +752,8 @@ double[5] e = a ~ d; // Все в порядке, явный запрос ма
Если в качестве результата конкатенации `~` явно указан массив фиксированной длины, никогда не происходит динамического выделения памяти: статически выделяется блок памяти, и результат конкатенации копируется в него. Если в качестве результата конкатенации `~` явно указан массив фиксированной длины, никогда не происходит динамического выделения памяти: статически выделяется блок памяти, и результат конкатенации копируется в него.
[Исходный код](src/chapter-4-2-6/)
[В начало ⮍](#4-2-6-конкатенация) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-2-6-конкатенация) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.2.7. Поэлементные операции ### 4.2.7. Поэлементные операции
@ -811,6 +839,8 @@ int[string] aa = [ "здравствуй":42, "мир":75 ];
auto aa = [ "здравствуй":42, "мир":75 ]; auto aa = [ "здравствуй":42, "мир":75 ];
``` ```
[Исходный код](src/chapter-4-4/)
[В начало ⮍](#4-4-ассоциативные-массивы) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-4-ассоциативные-массивы) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.4.1. Длина ### 4.4.1. Длина
@ -829,6 +859,8 @@ assert(aa.length == 2);
В отличие от одноименного свойства массивов, свойство `.length` ассоциативных массивов предназначено только для чтения. Тем не менее можно очистить ассоциативный массив, присвоив его переменной значение `null`. В отличие от одноименного свойства массивов, свойство `.length` ассоциативных массивов предназначено только для чтения. Тем не менее можно очистить ассоциативный массив, присвоив его переменной значение `null`.
[Исходный код](src/chapter-4-4-1/)
[В начало ⮍](#4-4-1-длина) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-4-1-длина) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.4.2. Чтение и запись ячеек ### 4.4.2. Чтение и запись ячеек
@ -852,7 +884,7 @@ aa["моцарелла"] = "mozzarella";
assert(aa["здравствуй"] == "ciao"); assert(aa["здравствуй"] == "ciao");
``` ```
Если вы попытаетесь прочитать значение по ключу, которого нет в ассоциативном массиве, возникнет исключительная ситуация. Но обычно генерация исключения в случае, когда ключ не обнаружен, слишком строгая мера, чтобы быть полезной, поэтому для чтения ассоциативных массивов предоставляется альтернативная функция, возвращающая значение по умолчанию, если ключ не найден в массиве. Она реализована в виде метода `get`, принимающего два аргумента. Если при вызове `aa.get(ключ, значeние_по_умолчанию)` в массиве найден `ключ`, то функция возвращает соответствующее ему значение, а выражение `значение_по__умолчанию` не вычисляется; иначе `значение_по__умолчанию` вычисляется и метод возвращает результат этого вычисления. Если вы попытаетесь прочитать значение по ключу, которого нет в ассоциативном массиве, возникнет исключительная ситуация. Но обычно генерация исключения в случае, когда ключ не обнаружен, слишком строгая мера, чтобы быть полезной, поэтому для чтения ассоциативных массивов предоставляется альтернативная функция, возвращающая значение по умолчанию, если ключ не найден в массиве. Она реализована в виде метода `get`, принимающего два аргумента. Если при вызове `aa.get(ключ, значeние_по_умолчанию)` в массиве найден `ключ`, то функция возвращает соответствующее ему значение, а выражение `значение_по_умолчанию` не вычисляется; иначе `значение_по_умолчанию` вычисляется и метод возвращает результат этого вычисления.
```d ```d
assert(aa["здравствуй"] == "ciao"); assert(aa["здравствуй"] == "ciao");
@ -870,6 +902,8 @@ assert("эй" !in aa);
// Попытка прочесть aa["эй"] вызвала бы исключение // Попытка прочесть aa["эй"] вызвала бы исключение
``` ```
[Исходный код](src/chapter-4-4-2/)
[В начало ⮍](#4-4-2-чтение-и-запись-ячеек) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-4-2-чтение-и-запись-ячеек) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.4.3. Копирование ### 4.4.3. Копирование
@ -887,6 +921,8 @@ assert(a1["Sam"] == 3.5); // наоборот
При этом у ассоциативных массивов, как и у обычных, есть свойство `.dup`, создающее поэлементную копию массива. При этом у ассоциативных массивов, как и у обычных, есть свойство `.dup`, создающее поэлементную копию массива.
[Исходный код](src/chapter-4-4-3/)
[В начало ⮍](#4-4-3-копирование) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-4-3-копирование) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.4.4. Проверка на равенство ### 4.4.4. Проверка на равенство
@ -902,6 +938,8 @@ a2["Bob"] = 18;
assert(a1 != a2); assert(a1 != a2);
``` ```
[Исходный код](src/chapter-4-4-4/)
[В начало ⮍](#4-4-4-проверка-на-равенство) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-4-4-проверка-на-равенство) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.4.5. Удаление элементов ### 4.4.5. Удаление элементов
@ -969,6 +1007,8 @@ foreach (k; gammaFunc.byKey())
} }
``` ```
[Исходный код](src/chapter-4-4-6/)
[В начало ⮍](#4-4-6-перебор-элементов) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-4-6-перебор-элементов) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
### 4.4.7. Пользовательские типы ### 4.4.7. Пользовательские типы
@ -1113,6 +1153,8 @@ void main()
Кодировка литерала определяется контекстом, в котором этот литерал используется. В предыдущем примере компилятор преобразует строковый литерал, без какой-либо обработки во время исполнения программы, из кодировки UTF-8 в кодировку UTF-16, а потом в кодировку UTF-32 (соответствующие типам `string`, `wstring` и `dstring`), хотя написание литералов во всех трех случаях одинаково. Если требуемая кодировка литерала не может быть однозначно определена, добавьте к нему суффикс `c`, `w` или `d` (например, `"как_здесь"d`): строка будет преобразована в кодировку UTF-8, UTF-16 или UTF-32 соответственно (см. раздел 2.2.5.2). Кодировка литерала определяется контекстом, в котором этот литерал используется. В предыдущем примере компилятор преобразует строковый литерал, без какой-либо обработки во время исполнения программы, из кодировки UTF-8 в кодировку UTF-16, а потом в кодировку UTF-32 (соответствующие типам `string`, `wstring` и `dstring`), хотя написание литералов во всех трех случаях одинаково. Если требуемая кодировка литерала не может быть однозначно определена, добавьте к нему суффикс `c`, `w` или `d` (например, `"как_здесь"d`): строка будет преобразована в кодировку UTF-8, UTF-16 или UTF-32 соответственно (см. раздел 2.2.5.2).
[Исходный код](src/chapter-4-5-4/)
[В начало ⮍](#4-5-4-массивы-знаков-бонусы-строки) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-5-4-массивы-знаков-бонусы-строки) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
#### 4.5.4.1. Цикл foreach применительно к строкам #### 4.5.4.1. Цикл foreach применительно к строкам
@ -1168,6 +1210,8 @@ foreach (dchar c; str)
В рассмотренном примере в инструкции `foreach` выполнялось перекодирование в направлении от «узкого» к более «широкому» представлению, но обратное преобразование также возможно. Например, можно начать со значения типа `dstring`, а затем просмотреть его по одному (закодированному) знаку типа `char`. В рассмотренном примере в инструкции `foreach` выполнялось перекодирование в направлении от «узкого» к более «широкому» представлению, но обратное преобразование также возможно. Например, можно начать со значения типа `dstring`, а затем просмотреть его по одному (закодированному) знаку типа `char`.
[Исходный код](src/chapter-4-5-4-1/)
[В начало ⮍](#4-5-4-1-цикл-foreach-применительно-к-строкам) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-5-4-1-цикл-foreach-применительно-к-строкам) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
## 4.6. Опасный собрат массива указатель ## 4.6. Опасный собрат массива указатель
@ -1230,6 +1274,8 @@ y += 100; // Хм...
Существует «урезанная» безопасная версия D, известная как SafeD (см. главу 11), также есть флаг компилятора, установка которого включает проверку принадлежности используемых в программе инструкций и типов данных этому безопасному подмножеству средств языка. Естественно, в безопасном D (SafeD) запрещено большинство операций с указателями. Встроенные массивы это важное средство, позволяющее создавать мощные, выразительные программы на SafeD. Существует «урезанная» безопасная версия D, известная как SafeD (см. главу 11), также есть флаг компилятора, установка которого включает проверку принадлежности используемых в программе инструкций и типов данных этому безопасному подмножеству средств языка. Естественно, в безопасном D (SafeD) запрещено большинство операций с указателями. Встроенные массивы это важное средство, позволяющее создавать мощные, выразительные программы на SafeD.
[Исходный код](src/chapter-4-6/)
[В начало ⮍](#4-6-опасный-собрат-массива-указатель) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки) [В начало ⮍](#4-6-опасный-собрат-массива-указатель) [Наверх ⮍](#4-массивы-ассоциативные-массивы-и-строки)
## 4.7. Итоги и справочник ## 4.7. Итоги и справочник
@ -1267,7 +1313,7 @@ y += 100; // Хм...
|`[t1, ..., tk]`|`T[k]`|Литерал массива, но только если тип `T[k]` запрошен явно; `T` определяется по типу `t1` (см. разделы [2.2.6](../02-%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F#2-2-6-литералы-массивов-и-ассоциативных-массивов) и [4.1](#4-1-динамические-массивы))| |`[t1, ..., tk]`|`T[k]`|Литерал массива, но только если тип `T[k]` запрошен явно; `T` определяется по типу `t1` (см. разделы [2.2.6](../02-%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F#2-2-6-литералы-массивов-и-ассоциативных-массивов) и [4.1](#4-1-динамические-массивы))|
|`a = b`|`ref T[n]`|Копирует содержимое одного массива в другой (см. раздел [4.2.4](#4-2-4-копирование-и-неявные-преобразования))| |`a = b`|`ref T[n]`|Копирует содержимое одного массива в другой (см. раздел [4.2.4](#4-2-4-копирование-и-неявные-преобразования))|
|`a[‹в›]`|`ref T`|Предоставляет доступ к элементу по индексу (символ `$` в `‹в›` заменяется на `a.length`, `‹в›` должно быть приводимым к типу `размер_t`; кроме того, должно соблюдаться условие `‹в› < a.length`) (см. раздел [4.1](#4-1-динамические-массивы))| |`a[‹в›]`|`ref T`|Предоставляет доступ к элементу по индексу (символ `$` в `‹в›` заменяется на `a.length`, `‹в›` должно быть приводимым к типу `размер_t`; кроме того, должно соблюдаться условие `‹в› < a.length`) (см. раздел [4.1](#4-1-динамические-массивы))|
|`a[в1 .. в2]`|`T[]/T[k]`|Получает срез массива `a` (символ `$` в `в1` и `в2` заменяется на `a.length`, `в1` и `в2` должны быть приводимыми к типу `размер_t`, также должно соблюдаться условие `в1 <= в2 && в2 <= a.length`) (см. раздел [4.2.3](#4-2-3-получение-срезов)))| |`a[в1 .. в2]`|`T[]/T[k]`|Получает срез массива `a` (символ `$` в `в1` и `в2` заменяется на `a.length`, `в1` и `в2` должны быть приводимыми к типу `размер_t`, также должно соблюдаться условие `в1 <= в2 && в2 <= a.length`) (см. раздел [4.2.3](#4-2-3-получение-срезов))|
|`a[]`|`T[]`|Поэлементная операция (см. раздел [4.1.7](#4-1-7-поэлементные-операции)) или приведение `a` (массива фиксированной длины) к типу динамического массива, то же, что и `a[0 .. $]`| |`a[]`|`T[]`|Поэлементная операция (см. раздел [4.1.7](#4-1-7-поэлементные-операции)) или приведение `a` (массива фиксированной длины) к типу динамического массива, то же, что и `a[0 .. $]`|
|`a.dup`|`T[]`|Получает дубликат массива (см. раздел [4.2.4](#4-2-4-копирование-и-неявные-преобразования))| |`a.dup`|`T[]`|Получает дубликат массива (см. раздел [4.2.4](#4-2-4-копирование-и-неявные-преобразования))|
|`a.length`|`размер_t`|Читает длину массива (см. раздел [4.2.1](#4-2-1-длина))| |`a.length`|`размер_t`|Читает длину массива (см. раздел [4.2.1](#4-2-1-длина))|

View File

@ -0,0 +1,13 @@
import std.stdio;
void main()
{
auto array1 = new short[55];
assert(array1.length == 55);
writeln(array1);
auto array2 = new int[10];
array2[9] = 42;
assert(array2[$ - 1] == 42);
writeln(array2);
}

View File

@ -0,0 +1,8 @@
void main()
{
auto array = new int[10];
array.length += 1000; // Расширяется
assert(array.length == 1010);
array.length /= 10; // Су­жа­ет­ся
assert(array.length == 101);
}

View File

@ -0,0 +1,8 @@
import std.stdio;
void main()
{
auto array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// На­пе­ча­тать толь­ко вто­рую по­ло­ви­ну
writeln(array[$ / 2 .. $]);
}

View File

@ -0,0 +1,8 @@
void main()
{
int[] array = [0, 1, 2];
int[] subarray = array[1 .. $];
assert(subarray.length == 2);
subarray[1] = 33;
assert(array[2] == 33);
}

View File

@ -0,0 +1,10 @@
void main()
{
auto a = ["hello", "world"];
auto b = a;
assert(a is b); // Тест прой­ден, у a и b од­ни те же гра­ни­цы
assert(a == b); // Ес­те­ст­вен­но, тест прой­ден
b = a.dup;
assert(a == b); // Тест прой­ден, a и b рав­ны, хо­тя за­ни­ма­ют раз­ные об­лас­ти па­мя­ти
assert(a !is b); // Тест прой­ден, a и b раз­лич­ны, хо­тя име­ют оди­на­ко­вое со­дер­жи­мое
}

View File

@ -0,0 +1,8 @@
void main()
{
int[] a = [0, 10, 20];
int[] b = a ~ 42;
assert(b == [0, 10, 20, 42]);
a = b ~ a ~ 15;
assert(a.length == 8);
}

View File

@ -0,0 +1,22 @@
import std.stdio;
void main()
{
auto a = [ 0.5, -0.5, 1.5, 2 ];
auto b = [ 3.5, 5.5, 4.5, -1 ];
auto c = new double[4]; // Па­мять под мас­сив долж­на быть уже вы­де­ле­на
c[] = (a[] + b[]) / 2; // Рас­счи­тать сред­нее ариф­ме­ти­че­ское a и b
assert(c == [ 2.0, 2.5, 3.0, 0.5 ]);
auto d = [1.0, 2.5, 3.6];
auto e = [4.5, 5.5, 1.4];
auto f = new double[3];
f[] += 4 * d[] + e[];
int[] g = new int[5];
int[] h = new int[5];
g[] = -1; // За­пол­нить все ячей­ки b зна­че­ни­ем -1
h[] = g[]; // Ско­пи­ро­вать все дан­ные из b в a
writeln(g);
writeln(h);
}

View File

@ -0,0 +1,15 @@
import std.stdio;
void main()
{
auto array = [0, 2, 4, 6, 8, 10];
array = array[0 .. $ - 2];
// Су­же­ние спра­ва на два эле­мен­та
assert(array == [0, 2, 4, 6]);
array = array[1 .. $];
// Су­же­ние сле­ва на один эле­мент
assert(array == [2, 4, 6]);
array = array[1 .. $ - 1];
// Су­же­ние с обе­их сто­рон
assert(array == [4]);
}

View File

@ -0,0 +1,18 @@
import std.conv, std.stdio;
int main(string[] args)
{
// Избавиться от имени программы
args = args[1 .. $];
while (args.length >= 2)
{
if (to!int(args[0]) != to!int(args[$ - 1]))
{
writeln("не палиндром");
return 1;
}
args = args[1 .. $ - 1];
}
writeln("палиндром");
return 0;
}

View File

@ -0,0 +1,9 @@
void main()
{
int[] a = [0, 10, 20, 30, 40, 50, 60, 70];
auto b = a[4 .. $];
a = a[0 .. 4];
// Сей­час a и b при­мы­ка­ют друг к дру­гу
a ~= [0, 0, 0, 0];
assert(b == [40, 50, 60, 70]); // Тест прой­ден; мас­сив a был пе­ре­не­сен в но­вую об­ласть па­мя­ти
}

View File

@ -0,0 +1,26 @@
import std.random;
import std.stdio;
void main()
{
// От 1 до 127 эле­мен­тов
auto array = new double[uniform(1, 128)];
foreach (i; 0 .. array.length)
{
array[i] = uniform(0.0, 1.0);
}
writeln(array);
foreach (ref element; array)
{
element = uniform(0.0, 1.0);
}
writeln(array);
auto copy = array.dup;
assert(array !is copy);
assert(array == copy);
}

View File

@ -0,0 +1,15 @@
import std.stdio;
void main()
{
int[5] array = [40, 30, 20, 10, 0];
auto slice1 = array[2 .. $]; // slice1 име­ет тип int[]
assert(slice1 == [20, 10, 0]);
auto slice2 = array[]; // Та­кой же, как array[0 .. $]
assert(slice2 == array);
int[10] a;
int[] b = a[1 .. 7]; // Все в по­ряд­ке
auto c = a[1 .. 7]; // Все в по­ряд­ке, c так­же име­ет тип int[]
int[6] d = a[1 .. 7]; // Все в по­ряд­ке, срез a[1 .. 7] ско­пи­ро­ван в d
}

View File

@ -0,0 +1,34 @@
import std.stdio;
int[3] fun(int[3] x, int[3] y)
{
// x и y ко­пии пе­ре­дан­ных ар­гу­мен­тов
x[0] = y[0] = 100;
return x;
}
double[3] fun2(double[] x)
{
double[3] result;
result[] = 2 * x[]; // Опе­ра­ция над мас­си­вом в це­лом
return result;
}
void main()
{
int[3] a = [1, 2, 3];
int[3] b = a;
a[1] = 42;
assert(b[1] == 2); // b не­за­ви­си­мая ко­пия a
auto c = fun(a, b); // c име­ет тип int[3]
assert(c == [100, 42, 3]);
writeln(c);
assert(b == [1, 2, 3]); // Вы­зов fun ни­как на от­ра­зил­ся на b
writeln(b);
double[3] point = [0, 0, 0];
double[] test = point; // Все в по­ряд­ке
auto r = fun2(point); // Все в по­ряд­ке, те­перь r име­ет тип double[3]
}

View File

@ -0,0 +1,15 @@
import std.stdio;
void main()
{
int[4] fixed = [1, 2, 3, 4];
auto anotherFixed = fixed;
assert(anotherFixed !is fixed); // Не то же са­мое (ко­пи­ро­ва­ние по зна­че­нию)
assert(anotherFixed == fixed); // Те же дан­ные
auto dynamic = fixed[]; // По­лу­ча­ет гра­ни­цы мас­си­ва fixed
assert(dynamic is fixed);
assert(dynamic == fixed); // Ес­те­ст­вен­но
dynamic = dynamic.dup; // Соз­да­ет ко­пию
assert(dynamic !is fixed);
assert(dynamic == fixed);
}

View File

@ -0,0 +1,10 @@
import std.stdio;
void main()
{
double[2] a;
double[] b = a ~ 0.5; // При­сое­ди­нить к double[2] зна­че­ние, по­лу­чить double[]
auto c = a ~ 0.5; // То же са­мое
double[3] d = a ~ 1.5; // Все в по­ряд­ке, яв­ный за­прос мас­си­ва фик­си­ро­ван­ной дли­ны
double[5] e = a ~ d; // Все в по­ряд­ке, яв­ный за­прос мас­си­ва фик­си­ро­ван­ной дли­ны
}

View File

@ -0,0 +1,29 @@
import std.stdio, std.random;
void main()
{
int[128] someInts;
int[3] a;
assert(a == [0, 0, 0]);
int[3] b = [1, 2, 3];
assert(b == [1, 2, 3]);
int[4] c = -1;
assert(c == [-1, -1, -1, -1]);
int[1024] d = void;
double[10] array;
foreach (i; 0 .. array.length)
{
array[i] = uniform(0.0, 1.0);
}
writeln(array);
foreach (ref element; array)
{
element = uniform(0.0, 1.0);
}
writeln(array);
}

View File

@ -0,0 +1,10 @@
import std.stdio;
void main()
{
string[int] aa;
assert(aa == null);
assert(aa.length == 0);
aa = [0:"zero", 1:"not zero"];
assert(aa.length == 2);
}

View File

@ -0,0 +1,21 @@
import std.stdio;
void main()
{
// Создать ассоциативный массив с соответствием строка/строка
auto aa = [ "здравствуй":"salve", "мир":"mundi" ];
// Перезаписать значения
aa["здравствуй"] = "ciao";
aa["мир"] = "mondo";
// Создать несколько новых пар ключ–значение
aa["капуста"] = "cavolo";
aa["моцарелла"] = "mozzarella";
writeln(aa);
assert(aa["здравствуй"] == "ciao");
// Ключ "здравствуй" существует, поэтому второй аргумент игнорируется
assert(aa.get("здравствуй", "salute") == "ciao");
// Ключ "здорово" не существует, возвратить второй аргумент
assert(aa.get("здорово", "buongiorno") == "buongiorno");
}

View File

@ -0,0 +1,11 @@
import std.stdio;
void main()
{
auto a1 = [ "Jane":10.0, "Jack":20, "Bob":15 ];
auto a2 = a1; // a1 и a2 ссылаются на одни данные
a1["Bob"] = 100; // Изменяя a1,...
assert(a2["Bob"] == 100); // ...мы изменяем a2...
a2["Sam"] = 3.5; // ...и
assert(a1["Sam"] == 3.5); // наоборот
}

View File

@ -0,0 +1,11 @@
import std.stdio;
void main()
{
auto a1 = [ "Jane":10.0, "Jack":20, "Bob":15 ];
auto a2 = [ "Jane":10.0, "Jack":20, "Bob":15 ];
assert(a1 !is a2);
assert(a1 == a2);
a2["Bob"] = 18;
assert(a1 != a2);
}

View File

@ -0,0 +1,26 @@
import std.stdio;
void main()
{
auto coffeePrices = [
"французская ваниль" : 262,
"ява" : 239,
"французская обжарка" : 224
];
foreach (kind, price; coffeePrices)
{
writefln("%s стоит %s руб. за 100 г", kind, price);
}
auto gammaFunc = [-1.5:2.363, -0.5:-3.545, 0.5:1.772];
double[] keys = gammaFunc.keys;
assert(keys == [ -1.5, -0.5, 0.5 ]);
writeln(keys);
foreach (k; gammaFunc.byKey())
{
writeln(k);
}
}

View File

@ -0,0 +1,9 @@
import std.stdio;
void main()
{
int[string] aa = ["здравсвтуй":42, "мир":75];
writeln(aa);
auto bb = ["здравсвтуй":42, "мир":75];
writeln(bb);
}

View File

@ -0,0 +1,20 @@
import std.stdio;
void main()
{
string str = "Hall\u00E5, V\u00E4rld!";
foreach (c; str)
{
write('[', c, ']');
}
writeln();
foreach (dchar c; str)
{
write('[', c, ']');
}
writeln();
}

View File

@ -0,0 +1,23 @@
import std.stdio;
import std.utf;
void main()
{
{
string a = "hello";
string b = a; // Переменная b теперь тоже указывает на значение "hello"
string c = b[0 .. 4]; // Переменная c указывает на строку "hell"
// Если бы такое присваивание было разрешено, это изменило бы a, b, и c:
// a[0] = 'H';
// Конкатенация оставляет переменные b и c нетронутыми:
a = 'H' ~ a[stride(a, 0) .. $];
assert(a == "Hello" && b == "hello" && c == "hell");
}
{
string a = "Независимо от представления \u03bb стоит \u20AC20.";
wstring b = "Независимо от представления \u03bb стоит \u20AC20.";
dstring c = "Независимо от представления \u03bb стоит \u20AC20.";
writeln(a, '\n', b, '\n', c);
}
}

View File

@ -0,0 +1,15 @@
import std.stdio;
void main()
{
auto arr = [ 5, 10, 20, 30 ];
auto p = arr.ptr;
assert(*p == 5);
++p;
assert(*p == 10);
++*p;
assert(*p == 11);
p += 2;
assert(*p == 30);
assert(p - arr.ptr == 3);
}