D (язык программирования) - D (programming language)

Язык программирования D
D Язык программирования logo.svg
ПарадигмаМультипарадигма: функциональный, императив, объектно-ориентированный
РазработаноУолтер Брайт, Андрей Александреску (с 2007 г.)
РазработчикD Language Foundation
Впервые появился8 декабря 2001 г.; 18 лет назад (2001-12-08)[1]
Стабильный выпуск
2.094.2[2] / 20 ноября 2020 г.; 16 дней назад (2020-11-20)[2]
Печатная дисциплинаПредполагаемый, статический, сильный
Операционные системыFreeBSD, Linux, macOS, Windows
ЛицензияСпособствовать росту[3][4][5]
Расширения имени файла.d[6][7]
Интернет сайтdlang.org
Основной реализации
DMD (эталонная реализация ), GCC,

GDC,

LDC, SDC
Под влиянием
C, C ++, C #, Эйфель,[8] Ява, Python
Под влиянием
Джинн, MiniD, Qore, Быстрый,[9] Вала, C ++ 11, C ++ 14, C ++ 17, C ++ 20, Идти, C #, и другие.

D, также известный как Dlang, это мультипарадигма язык системного программирования сделано Уолтер Брайт в Цифровой Марс и выпущен в 2001 году. Андрей Александреску присоединился к усилиям по проектированию и развитию в 2007 году. Хотя он возник как реинжиниринг C ++, D - отдельный язык. Он переработал некоторые основные функции C ++, а также сохранил характеристики других языков, в частности Ява, Python, Рубин, C #, и Эйфель.

Цели дизайна языка пытались объединить производительность и безопасность компилированные языки с выразительная сила современных динамические языки. Идиоматический Код D обычно так же быстр, как эквивалентный код C ++, но при этом короче.[10] Язык в целом не безопасный для памяти[11] но включает дополнительные атрибуты, предназначенные для проверки безопасности памяти.[12]

Вывод типа, автоматическое управление памятью и синтаксический сахар за общие типы позволить быстрее разработка, пока проверка границ, дизайн по контракту особенности и параллелизм -осведомленный система типов помочь уменьшить возникновение ошибки.[13]

Функции

D был разработан с учетом уроков, извлеченных из практического использования C ++, а не с чисто теоретической точки зрения. Хотя в языке используется много C и концепции C ++, он также отбрасывает некоторые или использует различные подходы (и синтаксис) для достижения некоторых целей. Как такового это не так источник совместим (и не стремится к этому) с исходным кодом C и C ++ в целом (некоторые более простые кодовые базы этих языков могут, по счастливой случайности, работать с D или потребовать некоторых перенос ). D, однако, был ограничен в своем дизайне правилом, согласно которому любой код, разрешенный как для C, так и для D, должен вести себя одинаково. D получил некоторые функции до C ++, такие как закрытие, анонимные функции, выполнение функции во время компиляции, диапазоны, встроенные концепции итерации контейнеров и вывод типа. D расширяет функциональность C ++, также реализуя дизайн по контракту, модульное тестирование, истинный модули, вывоз мусора, первый класс массивы, ассоциативные массивы, динамические массивы, нарезка массива, вложенные функции, ленивая оценка, выполнение кода с ограниченной областью видимости (отложенное) и переработанный шаблон синтаксис. D сохраняет способность C ++ выполнять низкоуровневое программирование и добавить встроенный ассемблер. C ++ множественное наследование был заменен на стиль Java одинарное наследование с интерфейсы и миксины. С другой стороны, декларация, утверждение и выражение D синтаксис полностью совпадает с C ++.

В встроенный ассемблер типизирует различия между D и языками приложений, например Ява и C #. Встроенный ассемблер позволяет программистам вводить машинно-зависимые код сборки в стандартном коде D - метод, используемый системными программистами для доступа к низкоуровневым функциям процессор необходимо для запуска программ, которые напрямую взаимодействуют с базовым аппаратное обеспечение, Такие как операционные системы и драйверы устройств, а также написание высокопроизводительного кода (т.е. с использованием векторных расширений, SIMD ), который компилятор сложно сгенерировать автоматически.

D имеет встроенную поддержку комментариев к документации, что позволяет автоматически создание документации.

Парадигмы программирования

D поддерживает пять основных парадигмы программирования: императив, объектно-ориентированный, метапрограммирование, функциональный и одновременный (актерская модель ).

Императив

Императивное программирование в D почти идентично программированию в C. Функции, данные, операторы, объявления и выражения работают так же, как и в C, и к библиотеке времени выполнения C можно обращаться напрямую. С другой стороны, некоторые заметные различия между D и C в области императивного программирования включают: для каждого конструкция цикла, которая позволяет перебирать коллекцию в цикле, и вложенные функции, которые являются функциями, которые объявлены внутри другого и могут обращаться к охватывающей функции локальные переменные.

импорт стандартное.stdio;пустота главный() {    int множитель = 10;    int масштабированный(int Икс) { возвращаться Икс * множитель; }    для каждого (я; 0 .. 10) {        writefln(«Привет, мир% d! Scaled =% d», я, масштабированный(я));    }}

D также включает динамические массивы и ассоциативные массивы по умолчанию в языке.

Символы (функции, переменные, классы) можно объявлять в любом порядке - предварительные декларации не требуются. Точно так же импорт может выполняться почти в любом порядке и даже иметь область видимости (т.е. импортировать некоторый модуль или его часть только внутри функции, класса или unittest).

D поддерживает перегрузка функции.

Объектно-ориентированный

Объектно-ориентированное программирование в D основано на единой иерархии наследования со всеми классами, производными от класса Object. D не поддерживает множественное наследование; вместо этого он использует стиль Java интерфейсы, которые сравнимы с чистыми абстрактными классами C ++, и миксины, который отделяет общие функции от иерархии наследования. D также позволяет определять статические и конечные (не виртуальные) методы в интерфейсах.

Поддержка интерфейсов и наследования в D ковариантные типы для возвращаемых типов переопределенных методов.

D поддерживает перегрузка оператора, переадресация типа, а также необязательный заказ динамическая отправка.

Классы (и интерфейсы) в D могут содержать инварианты которые автоматически проверяются до и после входа в общедоступные методы. Это часть дизайн по контракту методология.

Многие аспекты классов (и структур) могут быть самоуверенный автоматически во время компиляции (форма отражение с помощью типовые черты) и во время выполнения (RTII / TypeInfo), чтобы облегчить общий код или автоматическую генерацию кода (обычно с использованием методов времени компиляции).

Метапрограммирование

Метапрограммирование поддерживается комбинацией шаблонов, выполнением функций во время компиляции, кортежи, и строковые миксины. Следующие примеры демонстрируют некоторые возможности D во время компиляции.

Шаблоны в D могут быть написаны в более императивном стиле по сравнению с функциональным стилем C ++ для шаблонов. Это обычная функция, которая вычисляет факториал номера:

Улонг факториал(Улонг п) {    если (п < 2)        возвращаться 1;    еще        возвращаться п * факториал(п-1);}

Здесь использование статический, если, Условная конструкция D во время компиляции демонстрируется для создания шаблона, который выполняет те же вычисления с использованием кода, аналогичного таковому для функции выше:

шаблон Факториал(Улонг п) {    статический если (п < 2)        перечислить Факториал = 1;    еще        перечислить Факториал = п * Факториал!(п-1);}

В следующих двух примерах шаблон и функция, определенные выше, используются для вычисления факториалов. Типы констант не нужно указывать явно, поскольку компилятор делает вывод об их типах из правых частей присвоений:

перечислить факт_7 = Факториал!(7);

Это пример выполнение функции во время компиляции. Обычные функции могут использоваться в постоянных выражениях времени компиляции при условии, что они соответствуют определенным критериям:

перечислить факт_9 = факториал(9);

В std.string.format функция выполняет printf -подобное форматирование данных (также во время компиляции через CTFE ) и "msg" прагма отображает результат во время компиляции:

импорт стандартное.нить : формат;прагма(сообщение, формат(«7! =% S», факт_7));прагма(сообщение, формат(«9! =% S», факт_9));

Строковые миксины в сочетании с выполнением функций во время компиляции позволяют генерировать D-код с использованием строковых операций во время компиляции. Это можно использовать для анализа предметно-ориентированные языки в код D, который будет скомпилирован как часть программы:

импорт FooToD; // гипотетический модуль, содержащий функцию, анализирующую исходный код Foo               // и возвращает эквивалентный код Dпустота главный() {    миксин(fooToD(импорт("example.foo")));}

Функциональный

D поддерживает функциональное программирование такие функции, как функциональные литералы, закрытие, рекурсивно-неизменяемые объекты и использование функции высшего порядка. Существует два синтаксиса анонимных функций, включая форму с несколькими операторами и «сокращенную» нотацию с одним выражением:[10]

int функция(int) грамм;грамм = (Икс) { возвращаться Икс * Икс; }; // от рукиграмм = (Икс) => Икс * Икс;          // сокращение

Есть два встроенных типа для функциональных литералов: функция, который является просто указателем на функцию, выделенную в стеке, и делегировать, который также включает указатель на окружающую среду. Вывод типа может использоваться с анонимной функцией, и в этом случае компилятор создает делегировать если он не может доказать, что указатель среды не нужен. Аналогичным образом, чтобы реализовать закрытие, компилятор помещает закрытые локальные переменные в кучу только в случае необходимости (например, если закрытие возвращается другой функцией и выходит из области видимости этой функции). При использовании вывода типа компилятор также добавит такие атрибуты, как чистый и ничто к типу функции, если он может доказать, что они применимы.

Другие функциональные особенности, такие как карри и общие функции высшего порядка, такие как карта, фильтр, и уменьшать доступны через стандартные библиотечные модули стандартный функциональный и стандартный алгоритм.

импорт стандартное.stdio, стандартное.алгоритм, стандартное.классифицировать;пустота главный(){    int[] а1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];    int[] а2 = [6, 7, 8, 9];    // должен быть неизменным, чтобы разрешить доступ изнутри чистой функции    неизменный вращаться = 5;    int mySum(int а, int б) чистый ничто // чистая функция    {        если (б <= вращаться) // ссылка на охватывающую область            возвращаться а + б;        еще            возвращаться а;    }    // передача делегата (закрытие)    авто результат = уменьшать!mySum(цепь(а1, а2));    Writeln("Результат: ", результат); // Результат: 15    // передача литерала делегата    результат = уменьшать!((а, б) => (б <= вращаться) ? а + б : а)(цепь(а1, а2));    Writeln("Результат: ", результат); // Результат: 15}

Альтернативно, вышеуказанные функциональные композиции могут быть выражены с использованием Единый синтаксис вызова функций (UFCS) для более естественного чтения слева направо:

    авто результат = а1.цепь(а2).уменьшать!mySum();    Writeln("Результат: ", результат);    результат = а1.цепь(а2).уменьшать!((а, б) => (б <= вращаться) ? а + б : а)();    Writeln("Результат: ", результат);

Параллельный

Концепции параллельного программирования реализованы в библиотеке и не требуют дополнительной поддержки со стороны компилятора. Однако система типа D и компилятор гарантируют, что совместное использование данных может быть обнаружено и управляемо прозрачно.

импорт стандартное.stdio : Writeln;импорт стандартное.классифицировать : йота;импорт стандартное.параллелизм : параллельно;пустота главный(){    для каждого (я; йота(11).параллельно) {        // Тело цикла foreach выполняется параллельно для каждого i        Writeln("обработка ", я);    }}

йота (11) .параллельно эквивалентно std.parallelism.parallel (йота (11)) с помощью UFCS.

Этот же модуль также поддерживает taskPool который можно использовать для динамического создания параллельных задач, а также для операций в стиле map-filter-reduce и fold с диапазонами (и массивами), что полезно в сочетании с функциональными операциями:

импорт стандартное.stdio : Writeln;импорт стандартное.алгоритм : карта;импорт стандартное.классифицировать : йота;импорт стандартное.параллелизм : taskPool;пустота главный(){  авто числа = йота(1.0, 1_000_000_000.0);  авто Икс = taskPool.уменьшать!"а + б"(      0.0, карта!«1.0 / (а * а)»(числа)  );  Writeln(«Сумма:», Икс);  // На Intel i7-3930X и gdc 9.3.0:  // 5140 мсек с использованием std.algorithm.reduce  // 888 мс с использованием std.parallelism.taskPool.reduce;   // На AMD Threadripper 2950X и gdc 9.3.0:  // 2864 мс с использованием std.algorithm.reduce  // 95 мс с использованием std.parallelism.taskPool.reduce}

В этом коде используется тот факт, что std.algorithm.map на самом деле не возвращает массив, а лениво оценивает диапазон, таким образом фактические элементы карты вычисляются каждой рабочей задачей параллельно автоматически.

Одновременный

Параллельное программирование полностью реализовано в библиотеке и не требует специальной поддержки со стороны компилятора. Возможны альтернативные реализации и методологии написания параллельного кода. Использование системы ввода D действительно помогает обеспечить безопасность памяти.

импорт стандартное.stdio, стандартное.параллелизм, стандартное.вариант;пустота фу(){    bool продолжение = истинный;    пока (продолжение)    {        получить( // Делегаты используются для соответствия типу сообщения.            (int сообщение) => Writeln("int получено:", сообщение),            (Tid отправитель) { продолжение = ложный; отправитель.Отправить(-1); },            (Вариант v) => Writeln("Хм?") // Вариант соответствует любому типу        );    }}пустота главный(){    авто tid = порождать(&фу); // создаем новый поток, выполняющий foo ()    для каждого (я; 0 .. 10)        tid.Отправить(я);   // отправляем несколько целых чисел    tid.Отправить(1.0f);    // отправляем поплавок    tid.Отправить("Привет"); // отправляем строку    tid.Отправить(thisTid); // отправляем структуру (Tid)    получить((int Икс) => Writeln("Основная ветка получила сообщение:", Икс));}

Управление памятью

Памятью обычно управляют с помощью вывоз мусора, но определенные объекты могут быть финализированы немедленно, когда они выходят за пределы области видимости. Это то, что используют большинство программ и библиотек, написанных на D.

В случае, если требуется больший контроль над расположением памяти и лучшая производительность, возможно явное управление памятью с помощью перегруженные операторы новый и Удалить, позвонив C с malloc и бесплатно напрямую или с реализацией пользовательских схем распределения (например, в стеке с откатом, выделением стиля RAII, подсчетом ссылок, подсчетом общих ссылок). Сборкой мусора можно управлять: программисты могут добавлять и исключать диапазоны памяти из-под наблюдения сборщиком, могут отключать и включать сборщик и принудительно запускать цикл генерации или полного сбора.[14] В руководстве приводится много примеров того, как реализовать различные высокооптимизированные схемы управления памятью, когда сборка мусора в программе неадекватна.[15]

В функциях структуры по умолчанию размещаются в стеке, а классы по умолчанию размещается в куче (со ссылкой только на экземпляр класса, находящийся в стеке). Однако это можно изменить для классов, например, используя стандартный шаблон библиотеки. std.typecons.scoped, или используя новый для структур и присвоения указателю вместо переменной на основе значений.[16]

В функции статические массивы (известного размера) размещаются в стеке. Для динамических массивов можно использовать core.stdc.stdlib.alloca функция (аналогична функции C alloca, чтобы выделить память в стеке. Возвращаемый указатель может быть использован (преобразован) в (типизированный) динамический массив с помощью среза (однако следует избегать изменения размера массива, включая добавление; и по очевидным причинам они не должны возвращаться из функции).[17]

А объем ключевое слово может использоваться как для аннотирования частей кода, так и для переменных и классов / структур, чтобы указать, что они должны быть уничтожены (вызван деструктор) сразу после выхода из области видимости. Независимо от того, какая память будет освобождена, также зависит от реализации и различий между классами и структурами.[18]

std.experimental.allocator содержит модульные и составные шаблоны распределителя для создания настраиваемых высокопроизводительных распределителей для особых случаев использования.[19]

SafeD

SafeD[20]- это имя, присвоенное подмножеству D, которое может быть гарантированно безопасно для памяти (нет записи в память, которая не была выделена или была повторно использована). Функции отмечены @безопасный проверяются во время компиляции, чтобы убедиться, что они не используют какие-либо функции, которые могут привести к повреждению памяти, такие как арифметика указателя и неконтролируемое приведение типов, а любые другие вызываемые функции также должны быть помечены как @безопасный или же @ доверенный. Функции могут быть отмечены @ доверенный для случаев, когда компилятор не может различить безопасное использование функции, отключенной в SafeD, и потенциальный случай повреждения памяти.[21]

Безопасность на протяжении всего срока службы

Изначально под знаменами DIP1000[22] и DIP25[23] (теперь часть спецификации языка[24]), D обеспечивает защиту от некоторых плохо сформированных конструкций, связанных с временем жизни данных.

Существующие в настоящее время механизмы в основном имеют дело с параметрами функций и стековой памятью, однако заявленная цель лидера языка программирования - обеспечить более тщательное рассмотрение времени жизни в языке программирования D.[25] (Под влиянием идей от Язык программирования Rust ).

Пожизненная безопасность заданий

В коде @safe проверяется время жизни присвоения, включающего ссылочный тип, чтобы гарантировать, что время жизни правопреемника больше, чем у назначенного.

Например:

@безопасный пустота тест(){    int tmp = 0; // #1    int* рад;    // #2    рад = &tmp;  // Если порядок объявлений # 1 и # 2 поменять местами, это не сработает.    {    	int Плохо = 45; // Срок действия «плохого» распространяется только на область, в которой он определен.        *рад = Плохо;   // Это кошерно.        рад = &Плохо;   // Срок службы рад больше, чем плохой, поэтому это совсем не кошерно.     }}

Аннотации времени жизни параметра функции в коде @safe

При применении к параметру функции, имеющему тип указателя или ссылки, ключевые слова возвращаться и объем ограничить время жизни и использование этого параметра.

Стандарт диктует следующее поведение:[26]

Класс храненияПоведение (и ограничения) параметра с классом хранения
объемссылки в параметре не могут быть экранированы. Игнорируется для параметров без ссылок
возвращатьсяПараметр может быть возвращен или скопирован в первый параметр, но в противном случае функция не может выйти из него. Такие копии требуются, чтобы не пережить аргументы, на основании которых они были получены. Игнорируется для параметров без ссылок

Аннотированный пример приведен ниже.

@безопасный:int* GP;пустота торин(объем int*);пустота гулять(int*);int* балин(возвращаться объем int* п, объем int* q, int* р){     GP = п; // ошибка, p уходит в глобальный gp     GP = q; // ошибка, q уходит в глобальный gp     GP = р; // Ok     торин(п); // хорошо, p не ускользает от торина ()     торин(q); // Ok     торин(р); // Ok     гулять(п); // ошибка, gloin () экранирует p     гулять(q); // ошибка, gloin () экранирует q     гулять(р); // хорошо, что gloin () ускользает от r     возвращаться п; // Ok     возвращаться q; // ошибка, не может вернуть 'scope' q     возвращаться р; // Ok}

Взаимодействие с другими системами

C с двоичный интерфейс приложения (ABI) поддерживается, а также все основные и производные типы C, обеспечивая прямой доступ к существующему коду и библиотекам C. D привязки доступны для многих популярных библиотек C. Кроме того, стандарт C библиотека является частью стандарта D.

В Microsoft Windows D может получить доступ Компонентная объектная модель (COM) код.

Если правильно позаботиться об управлении памятью, многие другие языки могут быть смешаны с D в одном двоичном файле. Например, компилятор GDC позволяет связывать коды C, C ++ и других поддерживаемых языков для смешивания. Код (функции) D также может быть помечен как использующий C, C ++, Pascal ABI и, таким образом, передаваться в библиотеки, написанные на этих языках, как обратные вызовы. Точно так же данные можно обменивать между кодами, написанными на этих языках, обоими способами. Обычно это ограничивает использование примитивных типов, указателей, некоторых форм массивов, объединений, структур и только некоторых типов указателей на функции.

Поскольку многие другие языки программирования часто предоставляют C API для написания расширений или запуска интерпретатора языков, D также может напрямую взаимодействовать с этими языками, используя стандартные привязки C (с тонким файлом интерфейса D). Например, существуют двунаправленные привязки для таких языков, как Python,[27] Lua[28][29] и другие языки, часто использующие методы генерации кода и отражения типов во время компиляции.

Взаимодействие с кодом C ++

D использует разрешительный, но реалистичный подход к взаимодействию с кодом C ++.[30]

Для кода D, обозначенного как внешний (C ++), указаны следующие особенности:

  • Соглашения по изменению имен должны совпадать с соглашениями C ++ на целевой машине.
  • Для вызовов функций ABI должен быть эквивалентным.
  • Таблица vtable должна соответствовать одиночному наследованию (единственный уровень, поддерживаемый спецификацией языка D).

Пространства имен C ++ используются через синтаксис extern (C ++, пространство имен) куда пространство имен это имя пространства имен C ++.

Пример взаимодействия C ++

Сторона C ++

#включают <iostream>с помощью пространство имен стандартное;учебный класс Основание{    общественный:        виртуальный пустота print3i(int а, int б, int c) = 0;};учебный класс Полученный : общественный Основание{    общественный:        int поле;        Полученный(int поле) : поле(поле) {}        пустота print3i(int а, int б, int c)        {            cout << "а =" << а << конец;            cout << "b =" << б << конец;            cout << "c =" << c << конец;        }        int мул(int фактор);};int Полученный::мул(int фактор){    возвращаться поле * фактор;}Полученный *createInstance(int я){    возвращаться новый Полученный(я);}пустота deleteInstance(Полученный *&d){    Удалить d;    d = 0;}

Сторона D

внешний(C++){    Абстрактные учебный класс Основание    {        пустота print3i(int а, int б, int c);    }    учебный класс Полученный : Основание    {        int поле;        @запрещать это();        отменять пустота print3i(int а, int б, int c);        окончательный int мул(int фактор);    }    Полученный createInstance(int я);    пустота deleteInstance(ссылка Полученный d);}пустота главный(){    импорт стандартное.stdio;    авто d1 = createInstance(5);    Writeln(d1.поле);    Writeln(d1.мул(4));    Основание b1 = d1;    b1.print3i(1, 2, 3);    deleteInstance(d1);    утверждать(d1 является ноль);    авто d2 = createInstance(42);    Writeln(d2.поле);    deleteInstance(d2);    утверждать(d2 является ноль);}

Лучше C

В языке программирования D есть официальное подмножество, известное как "Лучше C".[31] Это подмножество запрещает доступ к функциям D, требующим использования библиотек времени выполнения, отличных от C.

Включено с помощью флагов компилятора "-betterC" на DMD и LDC и "-fno-druntime" на GDC, Лучше C может вызывать только код D, скомпилированный под тем же флагом (и связанный код, отличный от D), но код, скомпилированный без Лучше C Параметр может вызывать код, скомпилированный с ним: это, однако, приведет к немного разному поведению из-за различий в том, как C и D обрабатывают утверждения.

Функции, доступные в подмножестве Better C

  • Неограниченное использование функций времени компиляции (например, функции динамического распределения D могут использоваться во время компиляции для предварительного выделения данных D)
  • Полные средства метапрограммирования
  • Вложенные функции, вложенные структуры, делегаты и лямбды
  • Функции-члены, конструкторы, деструкторы, операционная перегрузка и т. Д.
  • Полная модульная система
  • Нарезка массива и проверка границ массива
  • RAII
  • область действия (выход)
  • Защита памяти
  • Взаимодействие с C ++
  • COM-классы и классы C ++
  • утверждать сбои направляются в библиотеку времени выполнения C
  • выключатель со струнами
  • последний переключатель
  • модульный тест блоки

Функции, недоступные в подмножестве Better C

  • Вывоз мусора
  • TypeInfo и ModuleInfo
  • Встроенная многопоточность (например, core.thread)
  • Динамические массивы (хотя работают срезы статических массивов) и ассоциативные массивы
  • Исключения
  • синхронизированный и core.sync
  • Конструкторы или деструкторы статических модулей

История

Уолтер Брайт начал работу над новым языком в 1999 году. D был впервые выпущен в декабре 2001 года.[1] и достигла версии 1.0 в январе 2007 года.[32] Первая версия языка (D1) концентрировалась на императивной, объектно-ориентированной парадигме и парадигме метапрограммирования,[33] похож на C ++.

Некоторые члены сообщества D недовольны Фобосом, официальным лицом D время выполнения и стандартная библиотека, создал альтернативную среду выполнения и стандартную библиотеку под названием Tango. Первое публичное объявление о Tango было сделано через несколько дней после выпуска D 1.0.[34] В Tango был принят другой стиль программирования, основанный на ООП и высокой модульности. Tango - это проект, возглавляемый сообществом, поэтому он был более открыт для участия, что позволило ему развиваться быстрее, чем официальная стандартная библиотека. В то время Tango и Phobos были несовместимы из-за разных API поддержки времени выполнения (сборщик мусора, поддержка потоковой передачи и т. Д.). Это сделало невозможным использование обеих библиотек в одном проекте. Существование двух широко используемых библиотек привело к серьезным спорам из-за того, что одни пакеты используют Phobos, а другие - Tango.[35]

В июне 2007 года была выпущена первая версия D2.[2] Начало развития D2 сигнализировало о стабилизации D1.Первая версия языка была переведена на обслуживание, в нее были внесены только исправления и исправления ошибок реализации. D2 представлен критические изменения к языку, начиная с его первого экспериментального система констант. Позже D2 добавил множество других языковых функций, таких как закрытие, чистота, а также поддержка парадигм функционального и параллельного программирования. D2 также решил проблемы стандартной библиотеки, отделив среду выполнения от стандартной библиотеки. О завершении строительства порта D2 Tango было объявлено в феврале 2012 года.[36]

Выпуск Андрей Александреску книга Язык программирования D 12 июня 2010 г. произошла стабилизация D2, которую сегодня обычно называют просто «D».

В январе 2011 года разработка D перешла с отслеживания ошибок / патчей на GitHub. Это привело к значительному увеличению вклада в компилятор, среду выполнения и стандартную библиотеку.[37]

В декабре 2011 года Андрей Александреску объявил, что 31 декабря 2012 года будет прекращена поддержка первой версии языка D1.[38] Последний выпуск D1, D v1.076, состоялся 31 декабря 2012 г.[39]

Код официального компилятора D, Цифровой компилятор Mars D Уолтера Брайта, изначально был выпущен под заказ лицензия, квалифицируясь как источник доступен но не соответствует определение с открытым исходным кодом.[40] В 2014 году компилятор внешний интерфейс был повторно лицензированный в качестве Открытый исходный код под Лицензия на программное обеспечение Boost.[3] Этот повторно лицензированный код исключал серверную часть, которая была частично разработана в Symantec. 7 апреля 2017 года весь компилятор стал доступен по лицензии Boost после того, как Symantec дала разрешение на повторную лицензию и на серверную часть.[4][41][42][43] 21 июня 2017 года язык D был принят для включения в GCC.[44]

Начиная с GCC 9, GDC (сокращение от GNU D Compiler или GCC D Compiler), интерфейс языка D, основанный на интерфейсе с открытым исходным кодом DMD, был объединен с GCC.[45]

Реализации

Самые последние реализации D компилировать прямо в Машинный код для эффективного исполнения.

Готовые компиляторы:

  • DMD - The Цифровой компилятор Mars D Уолтер Брайт - официальный компилятор языка D; с открытым исходным кодом под Лицензия на программное обеспечение Boost.[3][4] Интерфейс DMD используется GDC (теперь в GCC) и LDC для улучшения совместимости между компиляторами. Изначально интерфейс был написан на C ++, но теперь большая часть его написана на самом D (самостоятельный хостинг). Оптимизаторы внутреннего и машинного кода основаны на компиляторе Symantec. Сначала он поддерживал только 32-разрядную архитектуру x86, но Уолтер Брайт добавил поддержку 64-разрядной версии amd64 и PowerPC. Позже бэкэнд и почти весь компилятор были перенесены с C ++ на D для полноценного самостоятельного размещения.
  • GCC - The Коллекция компиляторов GNU, объединенный GDC[46] в GCC 9 29.10.2018.[47] Первые рабочие версии GDC с GCC, основанные на GCC 3.3 и GCC 3.4 на 32-битной x86 на Linux и MacOS X[48] Выпущена 22 марта 2004. С тех пор GDC получил поддержку большего количества платформ, улучшил производительность и исправил ошибки, одновременно отслеживая исходный код DMD для интерфейса и спецификации языка.
  • LDC - Компилятор на основе интерфейса DMD, использующий LLVM в качестве серверной части его компилятора. Первая релизная версия была опубликована 9 января 2009 года.[49] Он поддерживает версию 2.0.[50]

Компиляторы игрушек и доказательств концепции:

  • Компилятор D для .NET - Серверная часть для компилятора языка программирования D.[51][52] Он компилирует код в Общий промежуточный язык (CIL) байт-код, а не машинный код. Затем CIL можно запустить через Общая языковая инфраструктура (CLI) виртуальная машина. Проект не обновлялся годами, и автор указал, что проект больше не активен.
  • SDC - The Глупый компилятор D использует пользовательский интерфейс и LLVM в качестве серверной части его компилятора. Он написан на языке D и использует планировщик для обработки разрешения символов, чтобы элегантно обрабатывать функции времени компиляции D. Этот компилятор в настоящее время поддерживает ограниченное подмножество языка.[53][54]

Используя вышеуказанные компиляторы и инструментальные средства, можно скомпилировать программы D для многих различных архитектур, включая x86, amd64, AArch64, PowerPC, MIPS64, DEC Alpha, Motorola m68k, Sparc, s390, WebAssembly. Основные поддерживаемые операционные системы: Windows и Linux, но различные компиляторы также поддерживают Mac OS X, FreeBSD, NetBSD, AIX, Solaris / OpenSolaris и Android либо в качестве хоста, либо в качестве цели, либо в качестве обоих. WebAssembly target (поддерживается через LDC и LLVM) может работать в любой среде WebAssembly, например в современном веб-браузере (Гугл Хром, Mozilla Firefox, Microsoft Edge, Apple Safari ) или выделенные виртуальные машины Wasm.

Инструменты разработки

Редакторы и интегрированные среды разработки (IDE), поддерживающие D, включают Затмение, Microsoft Visual Studio, SlickEdit, Emacs, vim, НАУКА, Смултрон, TextMate, MonoDevelop, Зевс,[55] и Geany среди прочего.[56]

  • Dexed (ранее Coedit)[57] графическая IDE, ориентированная на D, написанная на Object Pascal
  • Моно-Д[58] представляет собой многофункциональную кроссплатформенную графическую среду IDE, ориентированную на D, основанную на MonoDevelop / Xamarin Studio, в основном написанную на C #.
  • Плагины Eclipse для D включают: ДДТ[59] и Спуск (мертвый проект).[60]
  • Интеграция с Visual Studio обеспечивается VisualD.[61][62]
  • Код Visual Studio интеграция с расширениями как Dlang-Vscode[63] или Код-D.[64]
  • Vim поддерживает оба подсветка синтаксиса и завершение кода
  • Пакет доступен для TextMate, а Код :: Блоки IDE включает частичную поддержку языка. Однако стандартные функции IDE, такие как завершение кода или же рефакторинг пока недоступны, хотя они частично работают в Code :: Blocks (из-за сходства D с C).
  • Плагин для Xcode 3 доступен, D для Xcode, для поддержки проектов и разработки на основе D.[65]
  • Доступна надстройка для MonoDevelop с именем Mono-D.[66]
  • Доступен плагин автозаполнения KDevelop (а также его бэкэнд текстового редактора Kate).[67]

Кроме того, многие другие редакторы и IDE поддерживают выделение синтаксиса и частичное завершение кода / идентификатора для D.

Открытый исходный код D IDE для Windows существуют, некоторые написаны на D, например, Посейдон,[68] D-IDE,[69] и Entice Designer.[70]

Приложения D можно отлаживать с помощью любого отладчика C / C ++, например GDB или же WinDbg, хотя поддержка различных специфичных для языка D функций крайне ограничена. В Windows программы D можно отлаживать с помощью Ddbg или инструменты отладки Microsoft (WinDBG и Visual Studio) после преобразования отладочной информации с помощью cv2pdb. В ZeroBUGS отладчик для Linux имеет экспериментальную поддержку языка D. Ddbg можно использовать с различными IDE или из командной строки; ZeroBUGS имеет собственный графический интерфейс пользователя (GUI).

DustMite - это мощный инструмент для минимизации исходного кода D, полезный при поиске проблем с компилятором или тестированием.[71]

dub - популярный менеджер пакетов и сборки для приложений и библиотек D, который часто интегрируется в поддержку IDE.[72]

Примеры

Пример 1

Этот пример программы печатает аргументы командной строки. В главный функция - это точка входа в программу D, а аргументы представляет собой массив строк, представляющих аргументы командной строки. А нить в D - это массив символов, представленный неизменяемый (символ) [].

1 импорт стандартное.stdio: writefln;2 3 пустота главный(нить[] аргументы)4 {5     для каждого (я, аргумент; аргументы)6         writefln("args [% d] = '% s'", я, аргумент);7 }

В для каждого оператор может перебирать любую коллекцию. В этом случае он создает последовательность индексов (я) и значения (аргумент) из массива аргументы. Индекс я и ценность аргумент имеют их типы, выведенные из типа массива аргументы.

Пример 2

Ниже показано несколько возможностей D и компромиссов D-дизайна в короткой программе. Он перебирает строки текстового файла с именем words.txt, который содержит разные слова в каждой строке и печатает все слова, являющиеся анаграммами других слов.

 1 импорт стандартное.stdio, стандартное.алгоритм, стандартное.классифицировать, стандартное.нить; 2  3 пустота главный() { 4     dstring[] [dstring] подпись2слова; 5  6     для каждого (dchar[] ш; линии(Файл("words.txt"))) { 7         ш = ш.чавкать().снизить(); 8         неизменный подпись = ш.обман.Сортировать().релиз().idup; 9         подпись2слова[подпись] ~= ш.idup;10     }11 12     для каждого (слова; подпись2слова) {13         если (слова.длина > 1) {14             Writeln(слова.присоединиться(" "));15         }16     }17 }
  1. подпись2слова - это встроенный ассоциативный массив, который отображает ключи dstring (32-битные / символьные) на массивы dstrings. Это похоже на defaultdict (список) в Python.
  2. строки (Файл ()) лениво выводит строки с новой строкой. Затем его нужно скопировать с помощью idup для получения строки, которая будет использоваться для значений ассоциативного массива ( idup свойство массивов возвращает неизменный дубликат массива, который требуется, поскольку dstring тип на самом деле неизменяемый (dchar) []). Для встроенных ассоциативных массивов требуются неизменяемые ключи.
  3. В ~= добавляет новую строку dstring к значениям связанного динамического массива.
  4. снизить, присоединиться и чавкать - строковые функции, которые D позволяет использовать с синтаксисом метода. Название таких функций часто похоже на строковые методы Python. В снизить преобразует строку в нижний регистр, присоединиться(" ") объединяет массив строк в одну строку, используя один пробел в качестве разделителя, и чавкать удаляет новую строку из конца строки, если она есть. В w.dup.sort (). release (). idup более читабелен, но эквивалентен выпуск (sort (w.dup)). idup Например. Эта функция называется UFCS (унифицированный синтаксис вызова функций) и позволяет расширять любые встроенные или сторонние типы пакетов с помощью функций, подобных методам. Такой стиль написания кода часто упоминается как трубопровод (особенно когда используемые объекты вычисляются лениво, например итераторы / диапазоны) или Свободный интерфейс.
  5. В Сортировать - это функция std.algorithm, которая сортирует массив на месте, создавая уникальную подпись для слов, которые являются анаграммами друг друга. В релиз() метод для возвращаемого значения Сортировать() удобно хранить код как одно выражение.
  6. Второй для каждого выполняет итерацию по значениям ассоциативного массива, он может определить тип слова.
  7. подпись присваивается неизменной переменной, определяется ее тип.
  8. UTF-32 dchar [] используется вместо обычного UTF-8 char [] иначе Сортировать() отказывается его сортировать. Есть более эффективные способы написать эту программу, используя только UTF-8.

Использует

Известные организации, использующие язык программирования D для проектов, включают: Facebook,[73] eBay,[74] и Netflix.[75]

D успешно использовался для ААА игры,[76] языковые переводчики, виртуальные машины,[77][78] ан Операционная система ядро,[79] GPU программирование,[80] Веб-разработка,[81][82] числовой анализ,[83] Приложения с графическим интерфейсом,[84][85] а информационная система для пассажиров,[86] машинное обучение,[87] обработка текста, веб-серверы и серверы приложений и исследования.

Смотрите также

Рекомендации

  1. ^ а б "D Изменения в протоколе до 7 ноября 2005 г.". D Язык программирования 1.0. Цифровой Марс. Получено 1 декабря 2011.
  2. ^ а б c «Журнал изменений - язык программирования D». D Язык программирования 2.0. D Language Foundation. Получено 22 ноября 2020.
  3. ^ а б c "Интерфейс dmd теперь переключен на лицензию Boost". Получено 9 сентября 2014.
  4. ^ а б c "Серверная часть dmd преобразована в лицензию Boost". 7 апреля 2017 г.. Получено 9 апреля 2017.
  5. ^ "D 2.0 FAQ". Получено 11 августа 2015.
  6. ^ ""Язык программирования D - Fileinfo.com"". Получено 15 ноября 2020.[нужна цитата ]
  7. ^ ""Язык программирования D - dlang.org"". Получено 15 ноября 2020.[нужна цитата ]
  8. ^ Александреску, Андрей (2010). Язык программирования D (Первое изд.). Река Аппер Сэдл, Нью-Джерси: Аддисон-Уэсли. п.314. ISBN  978-0321635365.
  9. ^ «Создание assert () в Swift, часть 2: __FILE__ и __LINE__». Получено 25 сентября 2014.
  10. ^ а б «Выражения». Цифровой Марс. Получено 27 декабря 2012.
  11. ^ «На: размышления о D: интервью с Уолтером Брайтом». Хакерские новости. 30 августа 2016 г. «Это близко, и мы работаем над устранением оставшихся пробелов».
  12. ^ "Память-Safe-D-Spec". D Language Foundation.
  13. ^ Андрей Александреску (2 августа 2010 г.). Три интересные вещи о D.
  14. ^ "std.gc". D Язык программирования 1.0. Цифровой Марс. Получено 6 июля 2010.
  15. ^ "Управление памятью". D Язык программирования 2.0. Цифровой Марс. Получено 17 февраля 2012.
  16. ^ «Иди своей дорогой (Часть первая: стек)». Блог D. Получено 7 мая 2020.
  17. ^ «Иди своей дорогой (Часть первая: стек)». Блог D. Получено 7 мая 2020.
  18. ^ «Атрибуты - язык программирования D». dlang.org. Получено 7 мая 2020.
  19. ^ "std.experimental.allocator - язык программирования D". dlang.org. Получено 7 мая 2020.
  20. ^ Бартош Милевски. "Язык программирования SafeD - D". Получено 17 июля 2014.
  21. ^ Стивен Швейгоффер (28 сентября 2016 г.). "Как написать @trusted Code в D". Получено 4 января 2018.
  22. ^ "Указатели с ограничением". 3 апреля 2020.
  23. ^ «Запечатанные ссылки».
  24. ^ «Спецификация языка D: функции - возвращаемые параметры области».
  25. ^ «Право собственности и заимствования в D». 15 июля 2019.
  26. ^ «Спецификация языка D: функции - классы хранения функциональных параметров».
  27. ^ "PyD". 7 мая 2020. Получено 7 мая 2020.
  28. ^ Паркер, Майк. "Пакет derelict-lua на DUB". Реестр пакетов DUB. Получено 7 мая 2020.
  29. ^ Паркер, Майк. "Пакет bindbc-lua на DUB". Реестр пакетов DUB. Получено 7 мая 2020.
  30. ^ «Взаимодействие с C ++».
  31. ^ "Лучше C".
  32. ^ «Журнал изменений D». D Язык программирования 1.0. Цифровой Марс. Получено 11 января 2012.
  33. ^ "Вступление". D Язык программирования 1.0. Цифровой Марс. Получено 1 декабря 2011.
  34. ^ «Анонс новой библиотеки». Получено 15 февраля 2012.
  35. ^ "Wiki4D: Стандартная библиотека". Получено 6 июля 2010.
  36. ^ «Tango for D2: все пользовательские модули перенесены». Получено 16 февраля 2012.
  37. ^ Уолтер Брайт. "Re: GitHub или dsource?". Получено 15 февраля 2012.
  38. ^ Андрей Александреску. «D1 будет снято с производства 31 декабря 2012 г.». Получено 31 января 2014.
  39. ^ "Журнал изменений D". D Язык программирования 1.0. Цифровой Марс. Получено 31 января 2014.
  40. ^ "backendlicense.txt". Исходный код DMD. GitHub. Архивировано из оригинал 22 октября 2016 г.. Получено 5 марта 2012.
  41. ^ "Комментарий Reddit Уолтера Брайта". Получено 9 сентября 2014.
  42. ^ D-компилятор-unter-freier-Lizenz на linux-magazin.de (2017, на немецком языке)
  43. ^ переключить бэкэнд на Boost License # 6680 от Уолтера Брайта github.com
  44. ^ D Язык принят для включения в GCC
  45. ^ «Изменения, новые функции и исправления GCC 9 Release Series».
  46. ^ «GDC».
  47. ^ «Серия выпусков GCC 9 - Изменения, новые функции и исправления - Проект GNU - Фонд свободного программного обеспечения (FSF)». gcc.gnu.org. Получено 7 мая 2020.
  48. ^ «Еще один интерфейс для GCC». forum.dlang.org. Получено 7 мая 2020.
  49. ^ "Проект компилятора LLVM D на GitHub". Получено 19 августа 2016.
  50. ^ "BuildInstructionsPhobosDruntimeTrunk - ldc - D язык программирования - Trac". Получено 11 августа 2015.
  51. ^ "Проект D .NET на CodePlex". Получено 3 июля 2010.
  52. ^ Джонатан Аллен (15 мая 2009 г.). «Теперь доступен исходный код компилятора D.NET». InfoQ. Получено 6 июля 2010.
  53. ^ «DConf 2014: SDC, компилятор D как библиотека, автор Амори Сечет». Получено 8 января 2014.
  54. ^ "deadalnix / SDC". Получено 8 января 2014.
  55. ^ "Wiki4D: EditorSupport / ZeusForWindows". Получено 11 августа 2015.
  56. ^ «Wiki4D: поддержка редактора». Получено 3 июля 2010.
  57. ^ "Basile.B / dexed". GitLab. Получено 29 апреля 2020.
  58. ^ "Моно-Д - Д Вики". wiki.dlang.org. Получено 30 апреля 2020.
  59. ^ «Хостинг проектов Google». Получено 11 августа 2015.
  60. ^ "спуск". Получено 11 августа 2015.
  61. ^ "Язык программирования Visual D - D". Получено 11 августа 2015.
  62. ^ Шуэце, Райнер (17 апреля 2020 г.). "rainers / visuald: Visual D - расширение Visual Studio для языка программирования D". github.com. Получено 30 апреля 2020.
  63. ^ "dlang-vscode". Получено 21 декабря 2016.
  64. ^ "код-д". Получено 21 декабря 2016.
  65. ^ «Мишель Фортин - D для Xcode». Получено 11 августа 2015.
  66. ^ «Поддержка Mono-D - D для MonoDevelop». Получено 11 августа 2015.
  67. ^ "Дав1дде / люмен". GitHub. Получено 11 августа 2015.
  68. ^ "посейдон". Получено 11 августа 2015.
  69. ^ «Поддержка Mono-D - D для MonoDevelop». Получено 11 августа 2015.
  70. ^ "Entice Designer - Dprogramming.com - язык программирования D". Получено 11 августа 2015.
  71. ^ "Что такое DustMite?". Получено 29 апреля 2020.
  72. ^ "dlang / dub: система управления пакетами и сборкой для D". Получено 29 апреля 2020.
  73. ^ "Под капотом: деформация, быстрый препроцессор C и C ++". 28 марта 2014 г.. Получено 4 января 2018.
  74. ^ «Более быстрые инструменты командной строки в D». 24 мая 2017. Получено 4 января 2018.
  75. ^ «Знакомство с Vectorflow». 2 августа 2017 г.. Получено 4 января 2018.
  76. ^ «Квантовый прорыв: игры AAA с некоторым кодом D». Получено 4 января 2018.
  77. ^ "Виртуальная машина JavaScript Хиггса". Получено 4 января 2018.
  78. ^ «Реализация AD языка программирования ECMA 262 (Javascript)». Получено 4 января 2018.
  79. ^ «Основные моменты проекта: ядро ​​PowerNex». Получено 4 января 2018.
  80. ^ «DCompute: запуск D на графическом процессоре». 30 октября 2017 г.. Получено 4 января 2018.
  81. ^ "vibe.d - высокопроизводительный набор инструментов для асинхронного ввода-вывода, параллелизма и веб-приложений, написанный на D". Получено 4 января 2018.
  82. ^ «Основные моменты проекта: Diamond MVC Framework». 20 ноября 2017 г.. Получено 4 января 2018.
  83. ^ «Числовой возраст для D: Mir GLAS быстрее, чем OpenBLAS и Eigen». Получено 4 января 2018.
  84. ^ "О Тиликсе и Д: Интервью с Джеральдом Нанном". 11 августа 2017 г.. Получено 4 января 2018.
  85. ^ «Особенности проекта: DlangUI». Получено 4 января 2018.
  86. ^ «Основные моменты проекта: Funkwerk». Получено 4 января 2018.
  87. ^ "Netflix / vectorflow". GitHub.com. Netflix, Inc. 5 мая 2020 г.. Получено 7 мая 2020.

дальнейшее чтение

внешняя ссылка