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

редактировать
Многопарадигмальный язык системного программирования

Язык программирования D
D Язык программирования logo.svg
Парадигма Многопарадигма : функциональный, императивный, объектно-ориентированный
Разработано Уолтером Брайтом, Андреем Александреску (с 2007)
Разработчик D Language Foundation
Впервые появился8 декабря 2001 г.; 18 лет назад (2001-12-08)
Стабильный выпуск 2.094.1 / 18 октября 2020 г.; 7 дней назад (2020-10-18)
Дисциплина ввода Предполагаемый, статический, сильный
OS FreeBSD, Linux, macOS, Windows
Лицензия Boost
Расширения имени файла .d
Веб-сайтdlang.org
Основные реализации
DMD (эталонная реализация ), GCC,

GDC,

LDC, SDC
Под влиянием
C, C ++, C#, Eiffel, Java, Python
под влиянием
Genie, MiniD, Qore, Swift, Vala, C ++ 11, C ++ 14, C ++ 17, C ++ 20, Go, C# и др.

D, также известный как Dlang, является многопарадигмным языком системного программирования Создан Уолтером Брайтом на Digital Mars и выпущен в 2001 году. Андрей Александреску присоединился к проекту в 2007 году. Хотя он возник как реинжиниринг C ++, D - отдельный язык. Он переработал некоторые основные функции C ++, а также получил характеристики других языков, в частности Java, Python, Ruby, C# и Eiffel.

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

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

Содержание
  • 1 Возможности
    • 1.1 Парадигмы программирования
      • 1.1.1 Императив
      • 1.1.2 Объект -ориентированный
      • 1.1.3 Метапрограммирование
      • 1.1.4 Функциональное
      • 1.1.5 Параллельное
      • 1.1.6 Параллельное
    • 1.2 Управление памятью
    • 1.3 SafeD
      • 1.3.1 Безопасность в течение срока службы
      • 1.3.2 Пожизненная безопасность назначений
      • 1.3.3 Аннотации времени жизни параметров функции в коде @safe
    • 1.4 Взаимодействие с другими системами
      • 1.4.1 Взаимодействие с кодом C ++
        • 1.4.1.1 Пример взаимодействия с C ++
    • 1.5 Better C
      • 1.5.1 Возможности, доступные в подмножестве Better C
      • 1.5.2 Функции, недоступные в подмножестве Better C
  • 2 История
  • 3 Реализации
  • 4 Инструменты разработки
  • 5 Примеры
    • 5.1 Пример 1
    • 5.2 Пример 2
  • 6 Использование
  • 7 См. Также
  • 8 Ссылки
  • 9 Дополнительная литература
  • 10 Внешние ссылки
Возможности

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

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

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

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

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

Императивное

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

import std.stdio; void main () {int multiplier = 10; int scaled (int x) {вернуть x * множитель; } foreach (i; 0.. 10) {writefln ("Привет, мир% d! scaled =% d", i, scaled (i)); }}

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

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

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

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

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

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

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

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

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

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

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

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

ulong factorial (ulong n) {if (n < 2) return 1; else return n * factorial(n-1); }

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

template Factorial (ulong n) {static if (n < 2) enum Factorial = 1; else enum Factorial = n * Factorial!(n-1); }

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

enum fact_7 = Factorial! (7);

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

enum fact_9 = factorial (9);

Функция std.string.formatвыполняет printf -подобное форматирование данных (также во время компиляции, thr ough CTFE ), а прагма «msg» отображает результат во время компиляции:

import std.string: format; pragma (msg, format ("7! =% s", fact_7)); pragma (msg, format ("9! =% s", fact_9));

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

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

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

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

int function (int) g; г = (х) {вернуть х * х; }; // от руки g = (x) =>x * x; // сокращение

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

Другие функциональные возможности, такие как каррирование и общие функции высшего порядка, такие как map, filter и reduce доступны через стандартные библиотечные модули std.functionalи std.algorithm.

import std.stdio, std.algorithm, std.range; void main () {int a1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; int a2 = [6, 7, 8, 9]; // должно быть неизменным, чтобы разрешить доступ изнутри чистой функции immutable pivot = 5; int mySum (int a, int b) pure nothrow // чистая функция {if (b <= pivot) // ref to enclosing-scope return a + b; else return a; } // passing a delegate (closure) auto result = reduce!mySum(chain(a1, a2)); writeln("Result: ", result); // Result: 15 // passing a delegate literal result = reduce!((a, b) =>(b <= pivot) ? a + b : a)(chain(a1, a2)); writeln("Result: ", result); // Result: 15 }

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

auto result = a1.chain (a2).reduce! mySum (); writereln ("Result:", result); result = a1.chain (a2).reduce! ((a, b) =>(b <= pivot) ? a + b : a)(); writeln("Result: ", result);

Parallel

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

import std.stdio: Writeln; import std.range: iota; import std.parallelism: parallel; void main () {foreach (i; iota (11).parallel) {/ / Тело цикла foreach выполняется параллельно для каждого i Writeln ("processing", i);}}

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

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

import std.stdio: Writeln; импорт std.algorithm: map; импорт std.range: йота; импорт std.parallelism: taskPool; void main () {auto nums = iota (1.0, 1_000_000_000.0); auto x = taskPool.reduce! "a + b" (0.0, map! "1.0 / (a ​​* a)" (число)); 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 действительно помогает обеспечить безопасность памяти.

импортировать std.stdio, std.concurrency, std.variant; void foo () {bool cont = true; while (cont) {receive (// Делегаты используются для соответствия типу сообщения. (int msg) =>writereln ("int Receive:", msg), (Tid sender) {cont = false; sender.send (-1);}, (Variant v) =>Writeln ("да?") // Вариант соответствует любому типу); }} void main () {auto tid = spawn (foo); // порождаем новый поток, выполняющий foo () foreach (i; 0.. 10) tid.send (i); // отправляем несколько целых чисел tid.send (1.0f); // отправляем float tid.send ("hello"); // отправляем строку tid.send (thisTid); // отправляем структуру (Tid) receive ((int x) =>writereln ("Сообщение получено основным потоком:", x)); }

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

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

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

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

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

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

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

SafeD

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

Scope Lifetime Safety

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

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

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

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

Например:

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

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

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

Стандарт определяет следующее поведение:

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

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

@safe: int * gp; недействительный торин (область видимости *); пустота gloin (int *); int * balin (возвращаем область действия int * p, область действия int * q, int * r) {gp = p; // ошибка, p переходит в глобальный gp gp = q; // ошибка, q уходит в глобальный gp gp = r; // хорошо торин (p); // хорошо, p не выходит из торина () торин (q); // хорошо торин (r); // нормально gloin (p); // ошибка, gloin () ускользает p gloin (q); // ошибка, gloin () ускользает q gloin (r); // хорошо, что gloin () ускользает r return p; // нормально return q; // ошибка, не может вернуть 'scope' q return r; // 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, Lua и других языков, часто с использованием методов генерации кода во время компиляции и методов отражения типов во время компиляции.

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

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

Для кода D, помеченного как extern (C ++), указаны следующие функции :

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

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

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

Сторона C ++

#include с использованием пространства имен std; class Base {public: virtual void print3i (int a, int b, int c) = 0; }; class Derived: public Base {public: int field; Производное (int field): field (field) {} ​​void print3i (int a, int b, int c) {cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; } int mul(int factor); }; int Derived::mul(int factor) { return field * factor; } Derived *createInstance(int i) { return new Derived(i); } void deleteInstance(Derived *d) { delete d; d = 0; }

Сторона D

extern (C ++) {абстрактный класс Base {void print3i (int a, int b, int c); } class Derived: Base {int field; @ отключить это (); переопределить void print3i (int a, int b, int c); final int mul (множитель int); } Производный createInstance (int i); void deleteInstance (ref Derived d); } void main () {import std.stdio; авто d1 = createInstance (5); Writeln (d1.field); Writeln (d1.mul (4)); База b1 = d1; b1.print3i (1, 2, 3); deleteInstance (d1); assert (d1 имеет значение null); авто d2 = createInstance (42); Writeln (d2.field); deleteInstance (d2); assert (d2 имеет значение null); }

Better C

Язык программирования D имеет официальное подмножество, известное как «Better C». Это подмножество запрещает доступ к функциям D, требующим использования библиотек времени выполнения, отличных от C.

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

Возможности, доступные в подмножестве Better C

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

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

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

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

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

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

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

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

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

Код для официального компилятора D, компилятора Digital Mars D Уолтера Брайта, изначально был выпущен под специальной лицензией , квалифицируемый как доступный исходный код, но не соответствующий определению с открытым исходным кодом. В 2014 году компилятор интерфейс был повторно лицензирован как с открытым исходным кодом в рамках лицензии на программное обеспечение Boost. Этот повторно лицензированный код исключал серверную часть, которая была частично разработана в Symantec. 7 апреля 2017 года весь компилятор стал доступен по лицензии Boost после того, как Symantec дала разрешение на повторную лицензию и на серверную часть. 21 июня 2017 года язык D был принят для включения в GCC.

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

Реализации

Большинство текущих реализаций D компилируют непосредственно в машинный код для эффективного выполнения.

Готовые к производству компиляторы:

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

Игрушечные и экспериментальные компиляторы:

  • Компилятор D для.NET - серверная часть для компилятора языка программирования D 2.0.. Он компилирует код в байт-код Common Intermediate Language (CIL), а не в машинный код. Затем CIL можно запустить через виртуальную машину Common Language Infrastructure (CLI) . Проект не обновлялся годами, и автор указал, что проект больше не активен.
  • SDC - Stupid D Compiler использует пользовательский интерфейс и LLVM в качестве бэк-энда компилятора. конец. Он написан на языке D и использует планировщик для обработки разрешения символов, чтобы элегантно обрабатывать функции времени компиляции D. Этот компилятор в настоящее время поддерживает ограниченное подмножество языка.

Используя указанные выше компиляторы и инструментальные средства, можно компилировать программы 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 (поддерживается через LDC и LLVM) может работать в любой среде WebAssembly, например в современном веб-браузере (Google Chrome, Mozilla Firefox, Microsoft Edge, Apple Safari ) или выделенные виртуальные машины Wasm.

Development tools

Editors and integrated development environments (IDEs) supporting D include Eclipse, Microsoft Visual Studio, SlickEdit, Emacs, SciTE, Smultron, TextMate, MonoDevelop, Zeus, and Geany among others.

  • Dexed (formely Coedit) a D focused graphical IDE written in Object Pascal
  • Mono-D is a feature rich cross-platform D focused graphical IDE based on MonoDevelop / Xamarin Studio, primarily written in C#.
  • Eclipse plug-ins for D include: DDT and Descent (dead project).
  • Visual Studio integration is provided by VisualD.
  • Visual Studio Code integration with extensions as Dlang-Vscode or Code-D.
  • Vim supports both syntax highlighting and code completion
  • A bundle is available for TextMate, and the Code::Blocks IDE includes partial support for the language. However, standard IDE features such as code completion or refactoring are not yet available, though they do work partially in Code::Blocks (due to D's similarity to C).
  • A plugin for Xcode 3 is available, D for Xcode, to enable D-based projects and development.
  • An AddIn for MonoDevelop is available, named Mono-D.
  • KDevelop (as well as its text editor backend, Kate) autocompletion plugin is available.

Additionally many other editors and IDE support syntax highlighting and partial code / identifier completion for D.

Open source D IDEs for Windows exist, some written in D, such as Poseidon, D-IDE, and Entice Designer.

D applications can be debugged using any C/C++ debugger, like GDB or WinDbg, although support for various D-specific language features is extremely limited. On Windows, D programs can be debugged using Ddbg, or Microsoft debugging tools (WinDBG and Visual Studio), after having converted the debug information using cv2pdb. The ZeroBUGS debugger for Linux has experimental support for the D language. Ddbg can be used with various IDEs or from the command line; ZeroBUGS has its own graphical user interface (GUI).

A DustMite is a powerful tool for minimize D source code, useful when finding compiler or tests issues.

dub is a popular package and build manager for D applications and libraries, and is often integrated into IDE support.

Examples

Example 1

This example program prints its command line arguments. The mainfunction is the entry point of a D program, and argsis an array of strings representing the command line arguments. A stringin D is an array of characters, represented by immutable(char).

1 import std.stdio: writefln; 2 3 void main(string args) 4 { 5 foreach (i, arg; args) 6 writefln("args[%d] = '%s'", i, arg); 7 }

The foreachstatement can iterate over any collection. In this case, it is producing a sequence of indexes (i) and values (arg) from the array args. The index iand the value arghave their types inferred from the type of the array args.

Example 2

The following shows several D capabilities and D design trade-offs in a short program. It iterates over the lines of a text file named words.txt, which contains a different word on each line, and prints all the words that are anagrams of other words.

1 import std.stdio, std.algorithm, std.range, std.string; 2 3 void main() { 4 dstring [dstring] signature2words; 5 6 foreach (dchar w; lines(File("words.txt"))) { 7 w = w.chomp().toLower(); 8 immutable signature = w.dup.sort().release().idup; 9 signature2words[signature] ~= w.idup; 10 } 11 12 foreach (words; signature2words) { 13 if (words.length>1) { 14 writeln(words.join(" ")); 15 } 16 } 17 }
  1. signature2wordsis a built-in associative array that maps dstring (32-bit / char) keys to arrays of dstrings. It is similar to defaultdict(list)in Python.
  2. lines(File())yields lines lazily, with the newline. It h as затем будет скопирован с помощью idupдля получения строки, которая будет использоваться для значений ассоциативного массива (свойство idupмассивов возвращает неизменяемую копию массива, которая требуется, поскольку тип dstringна самом деле неизменяемый (dchar)). Для встроенных ассоциативных массивов требуются неизменяемые ключи.
  3. Оператор ~ =добавляет новую строку dstring к значениям связанного динамического массива.
  4. toLower, joinи chomp- строковые функции, которые D позволяет использовать с синтаксисом метода. Название таких функций часто похоже на строковые методы Python. toLowerпреобразует строку в нижний регистр, join ("")объединяет массив строк в одну строку с использованием одного пробела в качестве разделителя, а chompудаляет новую строку из конца строки, если она есть. w.dup.sort (). Release (). Idupболее читабелен, но эквивалентен, например, release (sort (w.dup)). Idup. Эта функция называется UFCS (унифицированный синтаксис вызова функций) и позволяет расширять любые встроенные или сторонние типы пакетов с помощью функций, подобных методам. Такой стиль написания кода часто упоминается как pipeline (особенно когда используемые объекты вычисляются лениво, например, итераторы / диапазоны) или Fluent interface.
  5. The sort- это функция std.algorithm, которая сортирует массив на месте, создавая уникальную подпись для слов, которые являются анаграммами друг друга. Метод release ()для возвращаемого значения sort ()удобен для хранения кода в виде одного выражения.
  6. Второй foreachвыполняет итерацию по значениям ассоциативного массива, он может сделать вывод о том, что тип слов.
  7. подписьприсвоена неизменной переменной, ее тип определяется.
  8. UTF-32 dcharиспользуется вместо обычного UTF-8 char, иначе sort ()отказывается сортировать его. Есть более эффективные способы написать эту программу, используя только UTF-8.
Использует

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

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

См. Также
  • icon Портал компьютерного программирования
Ссылки
Дополнительная литература
Внешние ссылки
В Викиучебнике есть книга на тему: Руководство для начинающих по D
В Wikibooks есть книга по теме: D Programming
Последняя правка сделана 2021-05-16 09:44:10
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте