1.1 и 1.2
This commit is contained in:
parent
ea3d7c4485
commit
2b58cd0390
|
@ -1,7 +1,7 @@
|
||||||
# Знакомство с языком D
|
# 1. Знакомство с языком D
|
||||||
|
|
||||||
- [1.1. Числа и выражения]()
|
- [1.1. Числа и выражения](#11-числа-и-выражения)
|
||||||
- [1.2. Инструкции]()
|
- [1.2. Инструкции](#12-инструкции)
|
||||||
- [1.3. Основы работы с функциями]()
|
- [1.3. Основы работы с функциями]()
|
||||||
- 1.4. Массивы и ассоциативные массивы
|
- 1.4. Массивы и ассоциативные массивы
|
||||||
- [1.4.1. Работа со словарем]()
|
- [1.4.1. Работа со словарем]()
|
||||||
|
@ -55,7 +55,7 @@ $ _
|
||||||
|
|
||||||
Программа `hello.d` начинается с инструкции
|
Программа `hello.d` начинается с инструкции
|
||||||
|
|
||||||
```sh
|
```d
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -65,4 +65,117 @@ import std.stdio;
|
||||||
|
|
||||||
Следующие разделы – это стремительная поездка по Дибургу. Небольшие показательные программы дают общее представление о языке. Основная цель повествования на данном этапе – обрисовать общую картину, а не дать ряд педантичных определений. Позже все аспекты языка будут рассмотрены с должным вниманием – в деталях.
|
Следующие разделы – это стремительная поездка по Дибургу. Небольшие показательные программы дают общее представление о языке. Основная цель повествования на данном этапе – обрисовать общую картину, а не дать ряд педантичных определений. Позже все аспекты языка будут рассмотрены с должным вниманием – в деталях.
|
||||||
|
|
||||||
|
## 1.1. Числа и выражения
|
||||||
|
|
||||||
|
Интересовались ли вы когда-нибудь ростом иностранцев? Давайте напишем простую программу, которая переводит наиболее распространенные значения роста в футах и дюймах в сантиметры.
|
||||||
|
|
||||||
|
```d
|
||||||
|
/*
|
||||||
|
Рассчитать значения роста в сантиметрах для заданного диапазона значений в футах и дюймах
|
||||||
|
*/
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Значения, которые никогда не изменятся
|
||||||
|
immutable inchesPerFoot = 12;
|
||||||
|
immutable cmPerInch = 2.54;
|
||||||
|
// Перебираем и пишем
|
||||||
|
foreach (feet; 5 .. 7)
|
||||||
|
{
|
||||||
|
foreach (inches; 0 .. inchesPerFoot)
|
||||||
|
{
|
||||||
|
writeln(feet, "'", inches, "''\t", (feet * inchesPerFoot + inches) * cmPerInch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
В результате выполнения программы будет напечатан аккуратный список в две колонки:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
5'0'' 152.4
|
||||||
|
5'1'' 154.94
|
||||||
|
5'2'' 157.48
|
||||||
|
...
|
||||||
|
6'10'' 208.28
|
||||||
|
6'11'' 210.82
|
||||||
|
```
|
||||||
|
|
||||||
|
Инструкция `foreach (feet; 5..7) {...}` – это цикл, где определена целочисленная переменная `feet`, с которой последовательно связываются значения 5 и 6 (значение 7 она не принимает, так как интервал открыт справа). Как и Java, C++ и C#, D поддерживает `/* многострочные комментарии */` и `// однострочные комментарии` (и, кроме того, документирующие комментарии, о которых позже). Еще одна интересная деталь нашей маленькой программы – способ объявления данных. Во-первых, введены две константы:
|
||||||
|
|
||||||
|
```d
|
||||||
|
immutable inchesPerFoot = 12;
|
||||||
|
immutable cmPerInch = 2.54;
|
||||||
|
```
|
||||||
|
|
||||||
|
Константы, значения которых никогда не изменятся, определяются с помощью ключевого слова `immutable`. Как и переменные, константы не требуют явного задания типа: тип задается значением, которым инициализируется константа или переменная. В данном случае литерал 12 говорит компилятору о том, что `inchesPerFoot` – это целочисленная константа (обозначается в D с помощью знакомого `int`); точно так же литерал `2.54` заставляет `cmPerInch` стать константой с плавающей запятой (типа `double`). Далее мы обнаруживаем те же магические способности у определений `feet` и `inches`: они выглядят как «обычные» переменные, но безо всяких «украшений», свидетельствующих о каком-либо типе. Это не делает программу менее безопасной по сравнению с той, где типы переменных и констант заданы явно:
|
||||||
|
|
||||||
|
```d
|
||||||
|
immutable int inchesPerFoot = 12;
|
||||||
|
immutable double cmPerInch = 2.54;
|
||||||
|
...
|
||||||
|
foreach (int feet; 5 .. 7)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
и так далее – только меньше лишнего. Компилятор разрешает не указывать тип явно только в случае, когда можно недвусмысленно определить его по контексту. Раз уж зашла речь о типах, давайте остановимся и посмотрим, какие числовые типы нам доступны.
|
||||||
|
|
||||||
|
Целые типы со знаком в порядке возрастания размера: `byte`, `short`, `int` и `long`, занимающие 8, 16, 32 и 64 бита соответственно. У каждого из этих типов есть «двойник» без знака того же размера, названный в соответствии с простым правилом: `ubyte`, `ushort`, `uint` и `ulong`. (Здесь нет модификатора `unsigned`, как в C). Типы с плавающей запятой: `float` (32-битное число одинарной точности в формате IEEE 754), `double` (64-битное в формате IEEE 754) и `real` (занимает столько, сколько позволяют регистры, предназначенные для хранения чисел с плавающей запятой, но не меньше 64 бит; например, на компьютерах фирмы Intel `real` – это так называемое расширенное 79-битное число двойной точности в формате IEEE 754).
|
||||||
|
|
||||||
|
Вернемся к нашим целым числам. Литералы, такие как `42`, подходят под определение любого числового типа, но заметим, что компилятор проверяет, достаточно ли вместителен «целевой» тип для этого значения. Поэтому определение
|
||||||
|
|
||||||
|
```d
|
||||||
|
immutable byte inchesPerFoot = 12;
|
||||||
|
```
|
||||||
|
|
||||||
|
ничем не хуже аналогичного без `byte`, поскольку `12` можно с таким же успехом представить 8 битами, а не 32. По умолчанию, если вывод о «целевом» типе делается по числу (как в программе-примере), целочисленные константы «воспринимаются» как `int`, а дробные – как `double`.
|
||||||
|
|
||||||
|
Вы можете построить множество выражений на D, используя эти типы, арифметические операторы и функции. Операторы и их приоритеты сходны с теми, что можно найти в языках-собратьях D: `+`, `-`, `*`, `/` и `%` для базовых арифметических операций, `==`, `!=`, `<`, `>`, `<=`, `>=` для сравнений, `fun(argument1, argument2)` для вызовов функций и т.д.
|
||||||
|
|
||||||
|
Вернемся к нашей программе перевода дюймов в сантиметры и отметим две достойные внимания детали вызова функции `writeln`. Первая: во `writeln` передаются 5 аргументов (а не один, как в той программе, что установила контакт между вами и миром D). Функция `writeln` очень похожа на средства ввода-вывода, встречающиеся в языках Паскаль (`writeln`), C (`printf`) и C++ (`cout`). Все они (включая `writeln` из D) принимают переменное число аргументов (так называемые функции с переменным числом аргументов). Однако в D пользователи могут определять собственные функции с переменным числом аргументов (чего нет в Паскале), которые всегда типизированы (в отличие от C), без излишнего переопределения операторов (как это сделано в С++). Вторая деталь: наш вызов `writeln` неуклюже сваливает в кучу информацию о форматировании и форматируемые данные. Обычно желательно отделять данные от представления. Поэтому давайте используем специальную функцию `writefln`, осуществляющую форматированный вывод:
|
||||||
|
|
||||||
|
```d
|
||||||
|
writefln("%s'%s''\t%s", feet, inches, (feet * inchesPerFoot + inches) * cmPerInch);
|
||||||
|
```
|
||||||
|
|
||||||
|
По-новому организованный вызов дает тот же вывод, но первый аргумент функции `writefln` полностью описывает формат представления. Со знака `%` начинаются спецификаторы формата (по аналогии с функцией `printf` из C): например `%d` – для целых чисел, `%f` – для чисел с плавающей запятой и `%s` – для строк.
|
||||||
|
|
||||||
|
Если вы использовали `printf` прежде, то могли бы почувствовать себя как дома, когда б не маленькая особенность: мы ведь выводим значения переменных типа `int` и `double` – как же получилось, что и те и другие описаны с помощью спецификатора `%s`, обычно применяемого для вывода строк? Ответ прост. Средства D для работы с переменным количеством аргументов дают `writefln` доступ к информации об исходных типах переданных аргументов. Благодаря такому подходу программа получает ряд преимуществ: 1) значение `%s` может быть расширено до «строкового представления по умолчанию для типа переданного аргумента» и 2) если не удалось сопоставить спецификатор формата с типами переданных аргументов, вы получите ошибку в чистом виде, а не загадочное поведение, присущее вызовам `printf` с неверно заданным форматом (не говоря уже о подрыве безопасности, возможном при вызове `printf` с непроверяемыми заранее форматирующими строками).
|
||||||
|
|
||||||
|
## 1.2. Инструкции
|
||||||
|
|
||||||
|
В языке D, как и в других родственных ему языках, любое выражение, после которого стоит точка с запятой, – это инструкция (например в программе «Hello, world!» сразу после вызова `writeln` есть ;). Действие инструкции сводится к вычислению выражения.
|
||||||
|
|
||||||
|
D – член семейства с фигурными скобками и с блочной областью видимости». Это означает, что вы можете объединять несколько команд в одну, помещая их в `{` и `}`, что порой обязательно, например при желании сделать сразу несколько вещей в цикле `foreach`. В случае единственной команды вы вправе смело опустить фигурные скобки. На самом деле, весь наш двойной цикл, вычисляющий значения роста, можно переписать так:
|
||||||
|
|
||||||
|
```d
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Значения, которые никогда не изменятся
|
||||||
|
immutable inchesPerFoot = 12;
|
||||||
|
immutable cmPerInch = 2.54;
|
||||||
|
// Перебираем и пишем
|
||||||
|
foreach (feet; 5 .. 7)
|
||||||
|
foreach (inches; 0 .. inchesPerFoot)
|
||||||
|
writeln(feet, "'", inches, "''\t", (feet * inchesPerFoot + inches) * cmPerInch);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
У пропуска фигурных скобок для одиночных инструкций есть как преимущество (более короткий код), так и недостаток – редактирование кода становится более утомительным (в процессе отладки придется повозиться с инструкциями, то добавляя, то удаляя скобки). Когда речь заходит о правилах расстановки отступов и фигурных скобок, мнения сильно расходятся. На самом деле, пока вы последовательны в своем выборе, все это не так важно, как может показаться. В качестве доказательства: стиль, предлагаемый в этой книге (обязательное заключение в операторные скобки даже одиночных инструкций, открывающая скобка на одной строке с соответствующим оператором, закрывающие скобки на отдельных строках), по типографским причинам отличается от реально применяемого автором. А раз он мог спокойно это пережить, не превратившись в оборотня, то и любой сможет.
|
||||||
|
|
||||||
|
Благодаря языку Python стал популярен иной способ отражения блочной структуры программы – с помощью отступов (чудесное воплощение принципа «форма соответствует содержанию»). Для программистов на других языках утверждение, что пробел имеет значение, – всего лишь нелепая фраза, но для тех, кто пишет на Python, это зарок. D обычно игнорирует пробелы, но он разработан с прицелом на легкость синтаксического разбора (т. е. чтобы при разборе не приходилось выяснять значения символов). А это подразумевает, что в рамках скромного «комнатного» проекта можно реализовать простой препроцессор, позволяющий использовать для выделения блоков инструкций отступы (как в Python) без каких-либо неудобств во время компиляции, исполнения и отладки программ.
|
||||||
|
|
||||||
|
Кроме того, вам должна быть хорошо знакома инструкция if:
|
||||||
|
|
||||||
|
```d
|
||||||
|
if (‹выражение›) ‹инструкция1› else ‹инструкция2›
|
||||||
|
```
|
||||||
|
|
||||||
|
Чисто теоретический вывод, известный как принцип структурного программирования, гласит, что все алгоритмы можно реализовать с помощью составных инструкций, `if`-проверок и циклов а-ля `for` и `foreach`. Разумеется, любой адекватный язык (как и D) предлагает гораздо больше, но мы пока постановим, что с нас довольно и этих инструкций, и двинемся дальше.
|
||||||
|
|
||||||
[^1]: «Shebang» (от shell bang: shell – консоль, bang – восклицательный знак), или «shabang» (# – sharp) – обозначение пути к компилятору или интерпретатору в виде `#!/путь/к/программе`. – *Прим. пер.*
|
[^1]: «Shebang» (от shell bang: shell – консоль, bang – восклицательный знак), или «shabang» (# – sharp) – обозначение пути к компилятору или интерпретатору в виде `#!/путь/к/программе`. – *Прим. пер.*
|
||||||
|
|
Loading…
Reference in New Issue