Готовый перевод "D"iving Into the D Programming Language / Погружение в язык Ди: 1.4.1 Building a Vocabulary
Например, давайте напишем простую программу по такому условию:
Считать текст состоящий из слов разделенных пробелами, и присвоить уникальный номер каждому отдельному слову. Вывести строки в таком виде: ID слово.
Этот маленький скрипт будет полезен если тебе необходимо произвести некоторые операции над текстом; создав словарь один раз, тебе нужно будет манипулировать только номерами, а не целыми словами.
Возможный подход к созданию такого словаря - накапливать уже пройденные (просмотренные) слова в такую разновидность словаря соотносящего слова целым числам.
При добавлении нового соответствия нам только необходимо убедиться в том, что целое число уникально ( надежный выбор - использовать текущую длину словаря равную ID 0, 1, 2, ...).
Давайте посмотрим как это можно сделать на D.
import std.stdio, std.string;
void main() {
uint[string] dictionary;
foreach (line; stdin.byLine()) {
// Разбиваем предложение на слова
// Добавляем каждое слово из предложения в словарь
foreach (word; splitter(strip(line))) {
if (word in dictionary) continue; // Nothing to do
auto newlD = dictionary.length;
dictionary[word] = newlD;
writeln(newlD, word);
}
}
}
В D, тип ассоциативного массива (хэш-таблицы), который соотносит значения типа K со значениями типа V, обозначается как V [K] .
Так что словарь типа uint [ string ] соотносящий строки с беззнаковыми целыми числами - как раз то что нам нужно для хранения связей слово-ID.
Выражение "word in dictionary" будет ненулевым, если ключ из word будет найден в словаре dictionary. И наконец, вставка в словарь делается при помощи "dictionary[word] = newlD".
Хотя это не сделано явно в программе выше, тип string на самом деле массив символов. Вообще, массивы с изменяемой длиной обозначаются как T[] и инициализируются несколькими способами:
int[] a = new int[20]; // Целочисленный массив заполненный 20 нулями.
int[] b = [ 1, 2, 3 ]; // Массив содержит 1, 2 и 3
В отличии от массивов в "C", в языке "D" массивы знают собственную длину, которую можно получить через свойство массива length. Присваивание же свойству length перераспределяет память под массив на указанную длину.
Доступ к массиву всегда сопровождается проверкой выхода за пределы. Код, который не боится риска выйти за границы массива, может получить указатель этого массива (через свойство arr.ptr) и затем использовать адресную арифметику без каких-либо проверок со стороны "D".
Есть также опция компилятора, отключающая проверку границ, если вам нужно выжать максимум производительности из чипа. Это позволяет иметь код, который безопасный по-умолчанию, но который может быть сделан более быстрым с чуть большими усилиями.
Вот так можно перебрать элементы массива, используя новую форму уже знакомого оператора foreach:
int[] arr = new int[20];
foreach (elem; arr) {
/* ... elem - это элемент массива для использования в коде */
}
Цикл выше связывает переменную elem с каждым элементом массива. Однако, присвоение elem нового значения не изменяет сам элемент массива - для этого нужно объявить elem с ключевым словом ref:
// Обнулить все элементы arr
foreach (ref elem; arr) {
elem = 0; // теперь значение попадёт напрямую в массив
}
Иногда нужно иметь не только элемент массива, но и его индекс - foreach может и это:
int[] months = new int[12];
foreach (i, ref e; months) { // здесь 'i' - индекс элемента 'e'
e = i + 1;
}
Код выше создаёт массив чисел 1, 2, ..., 12. Этот цикл эквивалентен слегка более развёрнутому коду ниже:
foreach (i; 0 .. months.length) {
months[i] = i + 1;
}
В D можно создавать и массивы фиксированной длины (статические массивы): например, int[5] - массив из 5 целых и неизменяемой длиной.
Массивы обладают семантикой "поверхностной копии", т.е. присвоение переменной одного массива другой, не создаёт отдельной копии - теперь просто два имени ссылаются на один и тот же участок памяти. Если всё же нужна копия, нужно воспользоваться свойством массива dup:
int[] a = new int[100];
int[] b = a; // теперь 'a' и 'b' ссылаются на один и тот же массив
// ++x увеличивает на 1 значение x
++b[10]; // b[10] теперь равно 1, равно как и a[10]
b = a.dup; // А вот теперь b - независимая копия 'a'
++b[10]; // b[10] теперь стало 2, а a[10] осталось равным 1
Внимание! Этот перевод, возможно, ещё не готов.
Его статус: идёт перевод
Переведено на Нотабеноиде
http://notabenoid.org/book/42515/164384
Переводчики: thornik, Born2frag86
Настройки
Готово:
