From 59ce161978ccaad26f7e9c31721fd2af7f6df9c0 Mon Sep 17 00:00:00 2001 From: Whitebyte Date: Thu, 15 Oct 2015 00:10:12 +0600 Subject: D language russian --- ru-ru/d-ru.html.markdown | 735 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 735 insertions(+) create mode 100644 ru-ru/d-ru.html.markdown diff --git a/ru-ru/d-ru.html.markdown b/ru-ru/d-ru.html.markdown new file mode 100644 index 00000000..33bff3b7 --- /dev/null +++ b/ru-ru/d-ru.html.markdown @@ -0,0 +1,735 @@ +--- +language: d +filename: learnd-ru.d +contributors: + - ["Anton Pastukhov", "http://dprogramming.ru/"] + - ["Robert Brights-Gray", "http://lhs-blog.info/"] +lang: ru-ru +--- +D - современный компилируемый язык общего назначения с Си-подобным синтаксисом, +который сочетает удобство, продуманный дизайн и высокую производительность. +D - это С++, сделанный правильно. + +```d +// Welcome to D! Это однострочный комментарий + +/* многострочный + комментарий */ + +/+ + // вложенные кометарии + + /* еще вложенные + комментарии */ + + /+ + // мало уровней вложенности? Их может быть сколько угодно. + +/ ++/ + +/* + Имя модуля. Каждый файл с исходным кодом на D — модуль. + Если имя не указано явно, то предполагается, что оно совпадает с именем + файла. Например, для файла "test.d" имя модуля будет "test", если явно + не указать другое + */ +module app; + +// импорт модуля. Std — пространство имен стандартной библиотеки (Phobos) +import std.stdio; + +// можно импортировать только нужные части, не обязательно модуль целиком +import std.exception : assert; + +// точка входа в программу — функция main, аналогично C/C++ +void main() +{ + writeln("Hello, world!"); +} + + + +/*** типы и переменные ***/ + +int a; // объявление переменной типа int (32 бита) +float b = 12.34; // тип с плавающей точкой +double с = 56.78; // тип с плавающей точкой (64 бита) + +/* + Численные типы в D, за исключением типов с плавающей точкой и типов + комплексных чисел, могут быть беззнаковыми. + В этом случае название типа начинается с префикса "u" +*/ +uint d = 10, ulong e = 11.12; +bool b = true; // логический тип +char d = 'd'; // UTF-символ, 8 бит. D поддерживает UTF "из коробки" +wchar = 'é'; // символ UTF-16 +dchar f; // и даже UTF-32, если он вам зачем-то понадобится + +string s = "для строк есть отдельный тип, это не просто массив char-ов из Си"; +wstring ws = "поскольку у нас есть wchar, должен быть и wstring"; +dstring ds = "...и dstring, конечно"; + +typeof(a) b = 6; // typeof возвращает тип своего выражения. + // В результате, b имеет такой же тип как и a + +// Тип переменной, помеченной ключевым словом auto, +// присваивается компилятором исходя из значения этой переменной +auto x = 1; // Например, тип этой переменной будет int. +auto y = 1.1; // этой — double +auto z = "Zed is dead!"; // а этой — string + +int[3] arr = [1, 2, 3]; // простой одномерный массив с фиксированным размером +int[] arr2 = [1, 2, 3, 4]; // динамический массив +int[string] aa = ["key1": 5, "key2": 6]; // ассоциативный массив + +/* + Cтроки и массивы в D — встроенные типы. Для их использования не нужно + подключать ни внешние, ни даже стандартную библиотеку, хотя в последней + есть множество дополнительных инструментов для работы с ними. + */ +immutalbe int ia = 10; // неизменяемый тип, + // обозначается ключевым словом immutable +ia += 1; // — вызовет ошибку на этапе компиляции + +// перечислимый (enumerable) тип, +// более правильный способ работы с константами в D +enum myConsts = { Const1, Const2, Const3 }; + +// свойства типов +writeln("Имя типа : ", int.stringof); // int +writeln("Размер в байтах : ", int.sizeof); // 4 +writeln("Минимальное значение : ", int.min); // -2147483648 +writeln("Максимальное значениеe : ", int.max); // 2147483647 +writeln("Начальное значение : ", int.init); // 0. Это значение, + // присвоенное по умолчанию + +// На самом деле типов в D больше, но все мы здесь описывать не будем, +// иначе не уложимся в Y минут. + + + +/*** Приведение типов ***/ + +// Простейший вариант +int i; +double j = double(i) / 2; + +// to!(имя типа)(выражение) - для большинства конверсий +import std.conv : to; // функция "to" - часть стандартной библиотеки, а не языка +double d = -1.75; +short s = to!short(d); // s = -1 + +/* + cast - если вы знаете, что делаете. Кроме того, это единственный способ + преобразования типов-указателей в "обычные" и наоборот +*/ +void* v; +int* p = cast(int*)v; + +// Для собственного удобства можно создавать псевдонимы +// для различных встроенных объектов +alias int newInt; // теперь можно обращаться к int так, как будто бы это newInt +newInt a = 5; + +alias newInt = int; // так тоже допустимо +alias uint[2] pair; // дать псевдоним можно даже сложным структурам данных + + + +/*** Операторы ***/ + +int x = 10; // присваивание +x = x + 1; // 11 +x -= 2; // 9 +x++; // 10 +++x; // 11 +x *= 2; // 22 +x /= 2; // 11 +x ^^ 2; // 121 (возведение в степень) +x ^^= 2; // 1331 (то же самое) + +string str1 = "Hello"; +string str2 = ", world!"; +string hw = str1 ~ str2; // Конкатенация строк + +int[] arr = [1, 2, 3]; +arr ~= 4; // [1, 2, 3, 4] - добавление элемента в конец массива + + + +/*** Логика и сравнения ***/ + +int x = 0, int y = 1; + +x == y; // false +x > y; // false +x < y; // true +x >= y; // false +x != y; // true. ! — логическое "не" +x > 0 || x < 1; // true. || — логическое "или" +x > 0 && x < 1; // false && — логическое "и" +x ^ y // true; ^ - xor (исключающее "или") + +// Тернарный оператор +auto y = (x > 10) ? 1 : 0; // если x больше 10, то y равен 1, + // в противном случае y равен нулю + + +/*** Управляющие конструкции ***/ + +// if - абсолютно привычен +if (a == 1) { + // .. +} else if (a == 2) { + // .. +} else { + // .. +} + +// switch +switch (a) { + case 1: + // делаем что-нибудь + break; + case 2: + // делаем что-нибудь другое + break; + case 3: + // делаем что-нибудь еще + break; + default: + // default обязателен, без него будет ошибка компиляции + break; +} + +// while +while (a > 10) { + // .. + if (number == 42) { + break; + } +} + +while (true) { + // бесконечный цикл +} + +// do-while +do { + // .. +} while (a == 10); + +// for +for (int number = 1; number < 11; ++number) { + writeln(number); // все абсолютно стандартно +} + +for ( ; ; ) { + // секции могут быть пустыми. Это бесконечный цикл в стиле Си +} + +// foreach - универсальный и самый "правильный" цикл в D +foreach (element; array) { + writeln(element); // для простых массивов +} + +foreach (key, val; aa) { + writeln(key, ": ", val); // для ассоциативных массивов +} + +foreach (c; "hello") { + writeln(c); // hello. Поскольку строки - это вариант массива, + // foreach применим и к ним +} + +foreach (number; 10..15) { + writeln(number); // численные интервалы можно указывать явным образом +} + +// foreach_reverse - в обратную сторону +auto container = [ 1, 2, 3 ]; +foreach_reverse (element; container) { + writefln("%s ", element); // 3, 2, 1 +} + +// foreach в массивах и им подобных структурах не меняет сами структуры +int[] a = [1,2,3,4,5]; +foreach (elem; array) { + elem *= 2; // сам массив останется неизменным +} + +writeln(a); // вывод: [1,2,3,4,5] Т.е изменений нет + +// добавление ref приведет к тому, что массив будет изменяться +foreach (ref elem; array) { + elem *= 2; // сам массив останется неизменным +} + +writeln(a); // [2,4,6,8,10] + +// foreach умеет расчитывать индексы элементов +int[] a = [1,2,3,4,5]; +foreach (ind, elem; array) { + writeln(ind, " ", elem); // через ind - доступен индекс элемента, + // а через elem - сам элемент +} + + + +/*** Функции ***/ + +test(42); // Что, вот так сразу? Разве мы где-то уже объявили эту функцию? + +// Нет, вот она. Это не Си, здесь объявление функции не обязательно должно быть +// до первого вызова +int test(int argument) { + return argument * 2; +} + + +// В D используется унифицированныйй синтаксис вызова функций +// (UFCS, Uniform Function Call Syntax), поэтому так тоже можно: +int var = 42.test(); + +// и даже так, если у функции нет аргументов: +int var2 = 42.test; + +// можно выстраивать цепочки: +int var3 = 42.test.test; + +/* + Аргументы в функцию передаются по значению (т. е. функция работает не с + оригинальными значениями, переданными ей, а с их локальными копиями. + Исключение составляют объекты классов, которые передаются по ссылке. + Кроме того, любой параметр можно передать в функцию по ссылке с помощью + ключевого слова ref +*/ +int var = 10; + +void fn1(int arg) { + arg += 1; +} + +void fn2(ref int arg) { + arg += 1; +} + +fn1(var); // var все еще = 10 +fn2(var); // теперь var = 11 + +// Возвращаемое значение тоже может быть auto, +// если его можно "угадать" из контекста +auto add(int x, int y) { + return x + y; +} + +auto z = add(x, y); // тип int - компилятор вывел его автоматически + +// Значения аргументов по умолчанию +float linearFunction(float k, float x, float b = 1) +{ + return k * x + b; +} + +auto linear1 = linearFunction(0.5, 2, 3); // все аргументы используются +auto linear2 = linearFunction(0.5, 2); // один аргумент пропущен, но в функции + // он все равно использован и равен 1 + +// допускается описание вложенных функций +float quarter(float x) { + float doubled(float y) { + return y * y; + } + + return doubled(doubled(x)); +} + +// функции с переменным числом аргументов +int sum(int[] a...) +{ + int s = 0; + foreach (elem; a) { + s += elem; + } + return s; +} + +auto sum1 = sum(1); +auto sum2 = sum(1,2,3,4); + +/* + модификатор "in" перед аргументами функций говорит о том, что функция имеет + право их только просматривать. При попытке модификации такого аргумента + внутри функции - получите ошибку +*/ +float printFloat(in float a) +{ + writeln(a); +} +printFloat(a); // использование таких функций - самое обычное + +// модификатор "out" позволяет вернуть из функции несколько результатов +// без посредства глобальных переменных или массивов +uint remMod(uint a, uint b, out uint modulus) +{ + uint remainder = a / b; + modulus = a % b; + return remainder; +} + +uint modulus; // пока в этой переменной ноль +uint rem = remMod(5,2,modulus); // наша "хитрая" функция, и теперь, + // в modulus - остаток от деления +writeln(rem, " ", modulus); // вывод: 2 1 + + + +/*** Структуры, классы, базовое ООП ***/ + +// Объявление структуры. Структуры почти как в Си +struct MyStruct { + int a; + float b; + + void multiply() { + return a * b; + } +} + +MyStruct str1; // Объявление переменной с типом MyStruct +str1.a = 10; // Обращение к полю +str1.b = 20; +auto result = str1.multiply(); +MyStruct str2 = {4, 8} // Объявление + инициальзация в стиле Си +auto str3 = MyStruct(5, 10); // Объявление + инициальзация в стиле D + + +// области видимости полей и методов - 3 способа задания +struct MyStruct2 { + public int a; + + private: + float b; + bool c; + + protected { + float multiply() { + return a * b; + } + } + /* + в дополнение к знакомым public, private и protected, в D есть еще + область видимости "package". Поля и методы с этим атрибутам будут + доступны изо всех модулей, включенных в "пакет" (package), но не + за его пределами. package - это "папка", в которой может храниться + несколько модулей. Например, в "import.std.stdio", "std" - это + package, в котором есть модуль stdio (и еще множество других) + */ + package: + string d; + + /* помимо этого, имеется еще один модификатор - export, который позволяет + использовать объявленный с ним идентификатор даже вне самой программы ! + */ + export: + string description; +} + +// Конструкторы и деструкторы +struct MyStruct3 { + this() { // конструктор. Для структур его не обязательно указывать явно, + // в этом случае пустой конструктор добавляется компилятором + writeln("Hello, world!"); + } + + + // а вот это конструкция, одна из интересных идиом и представлет собой + // конструктор копирования, т.е конструктор возвращающий копию структуры. + // Работает только в структурах. + this(this) + { + return this; + } + + ~this() { // деструктор, также необязателен + writeln("Awww!"); + } +} + +// Объявление простейшего класса +class MyClass { + int a; // в D по умолчанию данные-члены являются public + float b; +} + +auto mc = new MyClass(); // ...и создание его экземпляра +auto mc2 = new MyClass; // ... тоже сработает + +// Конструктор +class MyClass2 { + int a; + float b; + + this(int a, float b) { + this.a = a; // ключевое слово "this" - ссылка на объект класса + this.b = b; + } +} + +auto mc2 = new MyClass2(1, 2.3); + +// Классы могут быть вложенными +class Outer +{ + int m; + + class Inner + { + int foo() + { + return m; // можно обращаться к полям "родительского" класса + } + } +} + +// наследование +class Base { + int a = 1; + float b = 2.34; + + + // это статический метод, т.е метод который можно вызывать обращаясь + // классу напрямую, а не через создание экземпляра объекта + static void multiply(int x, int y) + { + writeln(x * y); + } +} + +Base.multiply(2, 5); // используем статический метод. Результат: 10 + +class Derived : Base { + string c = "Поле класса - наследника"; + + + // override означает то, что наследник предоставит свою реализацию метода, + // переопределив метод базового класса + override static void multiply(int x, int y) + { + super.multiply(x, y); // super - это ссылка на класс-предок или базовый класс + writeln(x * y * 2); + } +} + +auto mc3 = new Derived(); +writeln(mc3.a); // 1 +writeln(mc3.b); // 2.34 +writeln(mc3.c); // Поле класса - наследника + +// Финальный класс, наследовать от него нельзя +// кроме того, модификатор final работает не только для классов, но и для методов +// и даже для модулей ! +final class FC { + int a; +} + +class Derived : FC { // это вызовет ошибку + float b; +} + +// Абстрактный класс не можен быть истанциирован, но может иметь наследников +abstract class AC { + int a; +} + +auto ac = new AC(); // это вызовет ошибку + +class Implementation : AC { + float b; + + // final перед методом нефинального класса означает запрет возможности + // переопределения метода + final void test() + { + writeln("test passed !"); + } +} + +auto impl = new Implementation(); // ОК + + + +/*** Микшины (mixins) ***/ + +// В D можно вставлять код как строку, если эта строка известна на этапе +// компиляции. Например: +void main() { + mixin(`writeln("Hello World!");`); +} + +// еще пример +string print(string s) { + return `writeln("` ~ s ~ `");`; +} + +void main() { + mixin (print("str1")); + mixin (print("str2")); +} + + + +/*** Шаблоны ***/ + +/* + Шаблон функции. Эта функция принимает аргументы разеых типов, которые + подсталяются вместо T на этапе компиляции. "T" - это не специальный + символ, а просто буква. Вместо "T" может быть любое слово, кроме ключевого. + */ +void print(T)(T value) { + writefln("%s", value); +} + +void main() { + print(42); // В одну и ту же функцию передается: целое + print(1.2); // ...число с плавающей точкой, + print("test"); // ...строка +} + +// "Шаблонных" параметров может быть сколько угодно +void print(T1, T2)(T1 value1, T2 value2) { + writefln(" %s %s", value1, value2); +} + +void main() { + print(42, "Test"); + print(1.2, 33); +} + +// Шаблон класса +class Stack(T) +{ + private: + T[] elements; + + public: + void push(T element) { + elements ~= element; + } + + void pop() { + --elements.length; + } + + T top() const @property { + return elements[$ - 1]; + } + + size_t length() const @property { + return elements.length; + } +} + +void main() { + /* + восклицательный знак - признак шаблона В данном случае мы создаем + класс и указывем, что "шаблонное" поле будет иметь тип string + */ + auto stack = new Stack!string; + + stack.push("Test1"); + stack.push("Test2"); + + writeln(stack.top); + writeln(stack.length); + + stack.pop; + writeln(stack.top); + writeln(stack.length); +} + + + +/*** Диапазоны (ranges) ***/ + +/* + Диапазоны - это абстракция, которая позволяет легко использовать разные + алгоритмы с разными структурами данных. Вместо того, чтобы определять свои + уникальные алгоритмы для каждой структуры, мы можем просто указать для нее + несколько единообразных функций, определяющих, _как_ мы получаем доступ + к элементам контейнера, вместо того, чтобы описывать внутреннее устройство + этого контейнера. Сложно? На самом деле не очень. +*/ + +/* + Простейший вид диапазона - Input Range. Для того, чтобы превратить любой + контейнер в Input Range, достаточно реализовать для него 3 метода: + - empty - проверяет, пуст ли контейнер + - front - дает доступ к первому элементу контейнера + - popFront - удаляет из контейнера первый элемент +*/ +struct Student +{ + string name; + int number; + string toString() { + return format("%s(%s)", name, number); + } +} + +struct School +{ + Student[] students; +} + +struct StudentRange +{ + Student[] students; + + this(School school) { + this.students = school.students; + } + + bool empty() { + return students.length == 0; + } + + ref Student front() { + return students[0]; + } + + void popFront() { + students = students[1 .. $]; + } +} + +void main(){ + auto school = School([ + Student("Mike", 1), + Student("John", 2) , + Student("Dan", 3) + ]); + auto range = StudentRange(school); + writeln(range); // [Mike(1), John(2), Dan(3)] + writeln(school.students.length); // 3 + writeln(range.front()); // Mike(1) + range.popFront(); + writeln(range.empty()); // false + writeln(range); // [John(2), Dan(3)] +} +/* + Смысл в том, что нам не так уж важно внутреннее устройство контейнера, если + у нас есть унифицированные методы доступа к его элементам. + Кроме Input Range в D есть и другие типы диапазонов, которые требуют + реализации большего числа методов, зато дают больше контроля. Это большая + тема и мы не будем в подробностях освещать ее здесь. + + Диапазоны - это важная часть D, они используются в нем повсеместно. +*/ +``` +## Что дальше? + +[Официальный сайт](http://dlang.org/) +[Онлайн-книга](http://ddili.org/ders/d.en/) +[Официальная вики](http://wiki.dlang.org/) -- cgit v1.2.3 From 8aff0a65dc106f4718b8d5da27178757e4f41eba Mon Sep 17 00:00:00 2001 From: Anton Pastukhoff Date: Fri, 30 Oct 2015 20:10:22 +0500 Subject: Update d-ru.html.markdown --- ru-ru/d-ru.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ru-ru/d-ru.html.markdown b/ru-ru/d-ru.html.markdown index 33bff3b7..cbd5b127 100644 --- a/ru-ru/d-ru.html.markdown +++ b/ru-ru/d-ru.html.markdown @@ -39,7 +39,7 @@ module app; import std.stdio; // можно импортировать только нужные части, не обязательно модуль целиком -import std.exception : assert; +import std.exception : enforce; // точка входа в программу — функция main, аналогично C/C++ void main() @@ -60,7 +60,7 @@ double с = 56.78; // тип с плавающей точкой (64 бита) комплексных чисел, могут быть беззнаковыми. В этом случае название типа начинается с префикса "u" */ -uint d = 10, ulong e = 11.12; +uint d = 10; ulong e = 11; bool b = true; // логический тип char d = 'd'; // UTF-символ, 8 бит. D поддерживает UTF "из коробки" wchar = 'é'; // символ UTF-16 @@ -146,7 +146,7 @@ x++; // 10 ++x; // 11 x *= 2; // 22 x /= 2; // 11 -x ^^ 2; // 121 (возведение в степень) +x = x ^^ 2; // 121 (возведение в степень) x ^^= 2; // 1331 (то же самое) string str1 = "Hello"; @@ -160,7 +160,7 @@ arr ~= 4; // [1, 2, 3, 4] - добавление элемента в конец /*** Логика и сравнения ***/ -int x = 0, int y = 1; +int x = 0; int y = 1; x == y; // false x > y; // false -- cgit v1.2.3 From b9cde57bc7efdfd9b9ba8e5fdbe9932c11562d0d Mon Sep 17 00:00:00 2001 From: Anton Pastukhoff Date: Thu, 3 Dec 2015 17:04:28 +0500 Subject: Update d-ru.html.markdown fixed typo --- ru-ru/d-ru.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ru-ru/d-ru.html.markdown b/ru-ru/d-ru.html.markdown index cbd5b127..ecd6c44c 100644 --- a/ru-ru/d-ru.html.markdown +++ b/ru-ru/d-ru.html.markdown @@ -17,7 +17,7 @@ D - это С++, сделанный правильно. комментарий */ /+ - // вложенные кометарии + // вложенные комментарии /* еще вложенные комментарии */ -- cgit v1.2.3 From f854fe1111186a9b8ba36c8d6ed057461f376b35 Mon Sep 17 00:00:00 2001 From: Anton Pastukhoff Date: Sat, 12 Dec 2015 14:43:56 +0500 Subject: Update d-ru.html.markdown --- ru-ru/d-ru.html.markdown | 138 ++++++++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 60 deletions(-) diff --git a/ru-ru/d-ru.html.markdown b/ru-ru/d-ru.html.markdown index ecd6c44c..0a8726c9 100644 --- a/ru-ru/d-ru.html.markdown +++ b/ru-ru/d-ru.html.markdown @@ -1,16 +1,17 @@ ---- +/*--- language: d filename: learnd-ru.d contributors: - ["Anton Pastukhov", "http://dprogramming.ru/"] - ["Robert Brights-Gray", "http://lhs-blog.info/"] + - ["Andre Polykanine", "http://oire.me/"] lang: ru-ru --- D - современный компилируемый язык общего назначения с Си-подобным синтаксисом, который сочетает удобство, продуманный дизайн и высокую производительность. D - это С++, сделанный правильно. -```d +```d */ // Welcome to D! Это однострочный комментарий /* многострочный @@ -53,7 +54,7 @@ void main() int a; // объявление переменной типа int (32 бита) float b = 12.34; // тип с плавающей точкой -double с = 56.78; // тип с плавающей точкой (64 бита) +double c = 56.78; // тип с плавающей точкой (64 бита) /* Численные типы в D, за исключением типов с плавающей точкой и типов @@ -63,15 +64,17 @@ double с = 56.78; // тип с плавающей точкой (64 бита) uint d = 10; ulong e = 11; bool b = true; // логический тип char d = 'd'; // UTF-символ, 8 бит. D поддерживает UTF "из коробки" -wchar = 'é'; // символ UTF-16 +wchar e = 'é'; // символ UTF-16 dchar f; // и даже UTF-32, если он вам зачем-то понадобится string s = "для строк есть отдельный тип, это не просто массив char-ов из Си"; wstring ws = "поскольку у нас есть wchar, должен быть и wstring"; dstring ds = "...и dstring, конечно"; +string кириллица = "Имена переменных должны быть в Unicode, но не обязательно на латинице."; + typeof(a) b = 6; // typeof возвращает тип своего выражения. - // В результате, b имеет такой же тип как и a + // В результате, b имеет такой же тип, как и a // Тип переменной, помеченной ключевым словом auto, // присваивается компилятором исходя из значения этой переменной @@ -84,11 +87,11 @@ int[] arr2 = [1, 2, 3, 4]; // динамический массив int[string] aa = ["key1": 5, "key2": 6]; // ассоциативный массив /* - Cтроки и массивы в D — встроенные типы. Для их использования не нужно + Строки и массивы в D — встроенные типы. Для их использования не нужно подключать ни внешние, ни даже стандартную библиотеку, хотя в последней есть множество дополнительных инструментов для работы с ними. */ -immutalbe int ia = 10; // неизменяемый тип, +immutable int ia = 10; // неизменяемый тип, // обозначается ключевым словом immutable ia += 1; // — вызовет ошибку на этапе компиляции @@ -100,7 +103,7 @@ enum myConsts = { Const1, Const2, Const3 }; writeln("Имя типа : ", int.stringof); // int writeln("Размер в байтах : ", int.sizeof); // 4 writeln("Минимальное значение : ", int.min); // -2147483648 -writeln("Максимальное значениеe : ", int.max); // 2147483647 +writeln("Максимальное значение : ", int.max); // 2147483647 writeln("Начальное значение : ", int.init); // 0. Это значение, // присвоенное по умолчанию @@ -111,17 +114,13 @@ writeln("Начальное значение : ", int.init); // 0. Эт /*** Приведение типов ***/ -// Простейший вариант -int i; -double j = double(i) / 2; - // to!(имя типа)(выражение) - для большинства конверсий import std.conv : to; // функция "to" - часть стандартной библиотеки, а не языка double d = -1.75; short s = to!short(d); // s = -1 /* - cast - если вы знаете, что делаете. Кроме того, это единственный способ + cast - если вы знаете, что делаете. Кроме того, это единственный способ преобразования типов-указателей в "обычные" и наоборот */ void* v; @@ -129,7 +128,7 @@ int* p = cast(int*)v; // Для собственного удобства можно создавать псевдонимы // для различных встроенных объектов -alias int newInt; // теперь можно обращаться к int так, как будто бы это newInt +alias int newInt; // теперь можно обращаться к newInt так, как будто бы это int newInt a = 5; alias newInt = int; // так тоже допустимо @@ -203,6 +202,25 @@ switch (a) { break; } +// в D есть констукция "final switch". Она не может содержать секцию "defaul" +// и применяется, когда все перечисляемые в switch варианты должны быть +// обработаны явным образом + +int dieValue = 1; +final switch (dieValue) { + case 1: + writeln("You won"); + break; + + case 2, 3, 4, 5: + writeln("It's a draw"); + break; + + case 6: + writeln("I won"); + break; +} + // while while (a > 10) { // .. @@ -245,31 +263,33 @@ foreach (c; "hello") { foreach (number; 10..15) { writeln(number); // численные интервалы можно указывать явным образом + // этот цикл выведет значения с 10 по 15, но не 15, + // поскольку диапазон не включает в себя верхнюю границу } // foreach_reverse - в обратную сторону -auto container = [ 1, 2, 3 ]; +auto container = [1, 2, 3]; foreach_reverse (element; container) { writefln("%s ", element); // 3, 2, 1 } // foreach в массивах и им подобных структурах не меняет сами структуры -int[] a = [1,2,3,4,5]; +int[] a = [1, 2 ,3 ,4 ,5]; foreach (elem; array) { elem *= 2; // сам массив останется неизменным } -writeln(a); // вывод: [1,2,3,4,5] Т.е изменений нет +writeln(a); // вывод: [1, 2, 3, 4, 5] Т.е изменений нет // добавление ref приведет к тому, что массив будет изменяться foreach (ref elem; array) { - elem *= 2; // сам массив останется неизменным + elem *= 2; } -writeln(a); // [2,4,6,8,10] +writeln(a); // [2, 4, 6, 8, 10] -// foreach умеет расчитывать индексы элементов -int[] a = [1,2,3,4,5]; +// foreach умеет рассчитывать индексы элементов +int[] a = [1, 2, 3, 4, 5]; foreach (ind, elem; array) { writeln(ind, " ", elem); // через ind - доступен индекс элемента, // а через elem - сам элемент @@ -288,7 +308,7 @@ int test(int argument) { } -// В D используется унифицированныйй синтаксис вызова функций +// В D используется единый синтаксис вызова функций // (UFCS, Uniform Function Call Syntax), поэтому так тоже можно: int var = 42.test(); @@ -299,11 +319,11 @@ int var2 = 42.test; int var3 = 42.test.test; /* - Аргументы в функцию передаются по значению (т. е. функция работает не с + Аргументы в функцию передаются по значению (т.е. функция работает не с оригинальными значениями, переданными ей, а с их локальными копиями. Исключение составляют объекты классов, которые передаются по ссылке. Кроме того, любой параметр можно передать в функцию по ссылке с помощью - ключевого слова ref + ключевого слова "ref" */ int var = 10; @@ -318,7 +338,7 @@ void fn2(ref int arg) { fn1(var); // var все еще = 10 fn2(var); // теперь var = 11 -// Возвращаемое значение тоже может быть auto, +// Возвращаемое значение тоже может быть auto, // если его можно "угадать" из контекста auto add(int x, int y) { return x + y; @@ -373,13 +393,13 @@ printFloat(a); // использование таких функций - сам // без посредства глобальных переменных или массивов uint remMod(uint a, uint b, out uint modulus) { - uint remainder = a / b; + uint remainder = a / b; modulus = a % b; return remainder; } uint modulus; // пока в этой переменной ноль -uint rem = remMod(5,2,modulus); // наша "хитрая" функция, и теперь, +uint rem = remMod(5, 2, modulus); // наша "хитрая" функция, и теперь // в modulus - остаток от деления writeln(rem, " ", modulus); // вывод: 2 1 @@ -400,9 +420,9 @@ struct MyStruct { MyStruct str1; // Объявление переменной с типом MyStruct str1.a = 10; // Обращение к полю str1.b = 20; -auto result = str1.multiply(); -MyStruct str2 = {4, 8} // Объявление + инициальзация в стиле Си -auto str3 = MyStruct(5, 10); // Объявление + инициальзация в стиле D +auto result = str1.multiply(); +MyStruct str2 = {4, 8} // Объявление + инициализация в стиле Си +auto str3 = MyStruct(5, 10); // Объявление + инициализация в стиле D // области видимости полей и методов - 3 способа задания @@ -420,7 +440,7 @@ struct MyStruct2 { } /* в дополнение к знакомым public, private и protected, в D есть еще - область видимости "package". Поля и методы с этим атрибутам будут + область видимости "package". Поля и методы с этим атрибутом будут доступны изо всех модулей, включенных в "пакет" (package), но не за его пределами. package - это "папка", в которой может храниться несколько модулей. Например, в "import.std.stdio", "std" - это @@ -428,8 +448,8 @@ struct MyStruct2 { */ package: string d; - - /* помимо этого, имеется еще один модификатор - export, который позволяет + + /* помимо этого, имеется еще один модификатор - export, который позволяет использовать объявленный с ним идентификатор даже вне самой программы ! */ export: @@ -442,10 +462,10 @@ struct MyStruct3 { // в этом случае пустой конструктор добавляется компилятором writeln("Hello, world!"); } - - - // а вот это конструкция, одна из интересных идиом и представлет собой - // конструктор копирования, т.е конструктор возвращающий копию структуры. + + + // а вот это конструкция - одна из интересных идиом и представляет собой + // конструктор копирования, т.е конструктор, возвращающий копию структуры. // Работает только в структурах. this(this) { @@ -488,7 +508,7 @@ class Outer { int foo() { - return m; // можно обращаться к полям "родительского" класса + return m; // можно обращаться к полям "внешнего" класса } } } @@ -497,10 +517,10 @@ class Outer class Base { int a = 1; float b = 2.34; - - - // это статический метод, т.е метод который можно вызывать обращаясь - // классу напрямую, а не через создание экземпляра объекта + + + // это статический метод, т.е метод который можно вызывать, обращаясь + // к классу напрямую, а не через создание экземпляра объекта static void multiply(int x, int y) { writeln(x * y); @@ -511,13 +531,13 @@ Base.multiply(2, 5); // используем статический метод. class Derived : Base { string c = "Поле класса - наследника"; - - + + // override означает то, что наследник предоставит свою реализацию метода, // переопределив метод базового класса override static void multiply(int x, int y) { - super.multiply(x, y); // super - это ссылка на класс-предок или базовый класс + super.multiply(x, y); // super - это ссылка на класс-предок, или базовый класс writeln(x * y * 2); } } @@ -538,7 +558,7 @@ class Derived : FC { // это вызовет ошибку float b; } -// Абстрактный класс не можен быть истанциирован, но может иметь наследников +// Абстрактный класс не может быть истанциирован, но может иметь наследников abstract class AC { int a; } @@ -547,8 +567,8 @@ auto ac = new AC(); // это вызовет ошибку class Implementation : AC { float b; - - // final перед методом нефинального класса означает запрет возможности + + // final перед методом нефинального класса означает запрет возможности // переопределения метода final void test() { @@ -560,7 +580,7 @@ auto impl = new Implementation(); // ОК -/*** Микшины (mixins) ***/ +/*** Примеси (mixins) ***/ // В D можно вставлять код как строку, если эта строка известна на этапе // компиляции. Например: @@ -583,8 +603,8 @@ void main() { /*** Шаблоны ***/ /* - Шаблон функции. Эта функция принимает аргументы разеых типов, которые - подсталяются вместо T на этапе компиляции. "T" - это не специальный + Шаблон функции. Эта функция принимает аргументы разных типов, которые + подставляются вместо T на этапе компиляции. "T" - это не специальный символ, а просто буква. Вместо "T" может быть любое слово, кроме ключевого. */ void print(T)(T value) { @@ -633,8 +653,8 @@ class Stack(T) void main() { /* - восклицательный знак - признак шаблона В данном случае мы создаем - класс и указывем, что "шаблонное" поле будет иметь тип string + восклицательный знак - признак шаблона. В данном случае мы создаем + класс и указываем, что "шаблонное" поле будет иметь тип string */ auto stack = new Stack!string; @@ -660,9 +680,7 @@ void main() { несколько единообразных функций, определяющих, _как_ мы получаем доступ к элементам контейнера, вместо того, чтобы описывать внутреннее устройство этого контейнера. Сложно? На самом деле не очень. -*/ -/* Простейший вид диапазона - Input Range. Для того, чтобы превратить любой контейнер в Input Range, достаточно реализовать для него 3 метода: - empty - проверяет, пуст ли контейнер @@ -706,8 +724,8 @@ struct StudentRange void main(){ auto school = School([ - Student("Mike", 1), - Student("John", 2) , + Student("Mike", 1), + Student("John", 2) , Student("Dan", 3) ]); auto range = StudentRange(school); @@ -730,6 +748,6 @@ void main(){ ``` ## Что дальше? -[Официальный сайт](http://dlang.org/) -[Онлайн-книга](http://ddili.org/ders/d.en/) -[Официальная вики](http://wiki.dlang.org/) +- [Официальный сайт](http://dlang.org/) +- [Онлайн-книга](http://ddili.org/ders/d.en/) +- [Официальная вики](http://wiki.dlang.org/) -- cgit v1.2.3 From 5e6a0269b32bccca6872075dfd2b6be031236874 Mon Sep 17 00:00:00 2001 From: Anton Pastukhoff Date: Sat, 12 Dec 2015 14:44:12 +0500 Subject: Update d-ru.html.markdown --- ru-ru/d-ru.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ru-ru/d-ru.html.markdown b/ru-ru/d-ru.html.markdown index 0a8726c9..645eceeb 100644 --- a/ru-ru/d-ru.html.markdown +++ b/ru-ru/d-ru.html.markdown @@ -1,4 +1,4 @@ -/*--- +--- language: d filename: learnd-ru.d contributors: @@ -11,7 +11,7 @@ D - современный компилируемый язык общего на который сочетает удобство, продуманный дизайн и высокую производительность. D - это С++, сделанный правильно. -```d */ +```d // Welcome to D! Это однострочный комментарий /* многострочный -- cgit v1.2.3 From 3663b10bfab490e65f22a345e98d352ef93876e8 Mon Sep 17 00:00:00 2001 From: Anton Pastukhoff Date: Sat, 12 Dec 2015 14:46:10 +0500 Subject: Update d-ru.html.markdown --- ru-ru/d-ru.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ru-ru/d-ru.html.markdown b/ru-ru/d-ru.html.markdown index 645eceeb..fad5c69b 100644 --- a/ru-ru/d-ru.html.markdown +++ b/ru-ru/d-ru.html.markdown @@ -263,7 +263,7 @@ foreach (c; "hello") { foreach (number; 10..15) { writeln(number); // численные интервалы можно указывать явным образом - // этот цикл выведет значения с 10 по 15, но не 15, + // этот цикл выведет значения с 10 по 14, но не 15, // поскольку диапазон не включает в себя верхнюю границу } -- cgit v1.2.3 From 7b8929f0cc477fe5db4e189c4ce3d6a7fdbdc3fd Mon Sep 17 00:00:00 2001 From: Anton Pastukhoff Date: Sat, 12 Dec 2015 14:47:02 +0500 Subject: Update d-ru.html.markdown --- ru-ru/d-ru.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ru-ru/d-ru.html.markdown b/ru-ru/d-ru.html.markdown index fad5c69b..8f4233fd 100644 --- a/ru-ru/d-ru.html.markdown +++ b/ru-ru/d-ru.html.markdown @@ -713,7 +713,7 @@ struct StudentRange return students.length == 0; } - ref Student front() { + Student front() { return students[0]; } -- cgit v1.2.3