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

Язык программирования мультипарадигмальных систем

язык программирования D
ПарадигмаМультипарадигмальный : функциональный , императивный , объектно-ориентированный
РазработаноУолтер Брайт , Андрей Александреску (с 2007 г.)
РазработчикФонд языка D
Впервые появился8 декабря 2001 г .; 23 года назад [1] ( 2001-12-08 )
Стабильный релиз
2.109.1 [2]  / 1 июля 2024 г. ; 7 месяцев назад ( 1 июля 2024 )
Дисциплина печатиПредполагаемый , статический , сильный
ОСFreeBSD , Linux , macOS , Windows
ЛицензияУсиление [3] [4] [5]
Расширения имени файла[6] [7]
Веб-сайтdlang.org
Основные внедрения
DMD ( референтная реализация ), GCC,

ГДК,

НРС, СРС
Под влиянием
BASIC , [8] C , C++ , C# , Eiffel , [9] Java , Python , Ruby
Под влиянием
Genie, MiniD, Qore , Swift , [10] Vala , C++11 , C++14 , C++17 , C++20 , Go , C# , другие
  • Программирование на языке D в Wikibooks

D , также известный как dlang , — это многопарадигмальный системный язык программирования , созданный Уолтером Брайтом в Digital Mars и выпущенный в 2001 году. Андрей Александреску присоединился к проектированию и разработке в 2007 году. Хотя он возник как переработка C++ , сейчас D — это совсем другой язык. По мере своего развития он черпал вдохновение из других языков программирования высокого уровня . В частности, на него повлияли Java , Python , Ruby , C# и Eiffel .

Справочник по языку D описывает это следующим образом:

D — это системный язык программирования общего назначения с синтаксисом, похожим на C, который компилируется в машинный код. Он статически типизирован и поддерживает как автоматическое (сборка мусора), так и ручное управление памятью. Программы на D структурированы как модули, которые могут компилироваться отдельно и связываться с внешними библиотеками для создания машинных библиотек или исполняемых файлов. [11]

Функции

D несовместим по исходному коду с исходным кодом C и C++ в целом. Однако любой код, который является допустимым как в C, так и в D, должен вести себя одинаково.

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

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

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

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

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

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

D поддерживает пять основных парадигм программирования :

Императив

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

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

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

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

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

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

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

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

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

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

int function ( int ) g ; g = ( x ) { return x * x ; }; // длинная запись g = ( x ) => x * x ; // сокращенная запись                  

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

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

импорт станд.стдио , станд.алгоритм , станд.диапазон ;   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 ) // ссылка на охватывающую область действия return a + b ; else return a ; }                      // передача делегата (замыкание) auto result = reduce ! mySum ( chain ( a1 , a2 )); writeln ( "Result: " , result ); // Результат: 15         // передача делегата литерала result = reduce !(( a , b ) => ( b <= pivot ) ? a + b : a )( chain ( a1 , a2 )); writeln ( "Результат: " , result ); // Результат: 15 }                  

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

 auto result = a1.chain ( a2 ) .reduce ! mySum ( ); writeln ( "Результат: " , result ) ;      result = a1.chain ( a2 ) .reduce !(( a , b ) => ( b <= pivot ) ? a + b : a )(); writeln ( " Результат : " , result );               

Параллелизм

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

импорт std.stdio : writeln ; импорт std.range : iota ; импорт 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который может использоваться для динамического создания параллельных задач, а также операций map-filter-reduce и fold в диапазонах (и массивах), что полезно в сочетании с функциональными операциями. std.algorithm.mapвозвращает лениво вычисляемый диапазон, а не массив. Таким образом, элементы вычисляются каждой рабочей задачей параллельно автоматически.

импорт std.stdio : writeln ; импорт std.algorithm : map ; импорт std.range : iota ; импорт std.parallelism : taskPool ;            /* На 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 */ 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) " ( nums ) ) ;       writeln ( "Сумма: " , x ); } 

Параллелизм

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

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

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

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

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

ulong факториал ( ulong n ) { if ( n < 2 ) вернуть 1 ; иначе вернуть n * факториал ( n - 1 ); }              

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

шаблон Факториал ( ulong n ) { static if ( n < 2 ) enum Факториал = 1 ; else enum Факториал = n * Факториал !( n - 1 ); }                   

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

enum fact_7 = Факториал !( 7 );   

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

enum fact_9 = факториал ( 9 );   

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

импортировать std.string : format ; pragma ( msg , format ( "7!=%s" , fact_7 ) ); pragma ( msg , format ( " 9!=%s" , fact_9 ));       

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

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

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

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

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

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

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

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

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

SafeD

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

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

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

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

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

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

Например:

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

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

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

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

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

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

@безопасный :int * gp ; void thorin ( scope int *); void gloin ( int *); int * balin ( return scope int * p , scope int * q , int * r ) { gp = p ; // Ошибка, p переходит в глобальную переменную gp. gp = q ; // Ошибка, q переходит в глобальную переменную gp. gp = r ; // OK.                           thorin ( p ); // OK, p не экранируется thorin(). thorin ( q ); // OK. thorin ( r ); // OK.      глоин ( р ); // Ошибка, p выходит за пределы globin(). глоин ( q ); // Ошибка, q выходит из globin(). глоин ( р ); // Хорошо, что r экранирует glein().      return p ; // OK. return q ; // Ошибка, невозможно вернуть 'scope' q. return r ; // OK. }        

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

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

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

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

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

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

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

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

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

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

Сторона C++

импорт стандартный ; класс Base { public : virtual void print3i ( int a , int b , int c ) = 0 ; };             класс Производный : public Base { public : int field ; Производный ( int field ) : field ( field ) {}              void print3i ( int a , int b , int c ) { std :: println ( "a = {}" , a ); std :: println ( "b = {}" , b ); std :: println ( "c = {}" , c ); }               int mul ( int factor ); };  int Derived::mul ( int factor ) { return field * factor ; }       Производный * createInstance ( int i ) { return new Производный ( i ); }      void deleteInstance ( Производный *& d ) { удалить d ; d = 0 ; }        

Сторона D

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

Лучше С

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

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

Функции, включенные в Better C

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

Функции, исключенные из Better C

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

История

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

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

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

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

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

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

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

Реализации

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

Готовые к использованию компиляторы:

  • DMD – The Digital Mars D compiler by Walter Bright – официальный компилятор D; открытый исходный код по лицензии Boost Software License . [3] [4] Фронтенд DMD совместно используется GDC (теперь в GCC) и LDC для улучшения совместимости между компиляторами. Изначально фронтенд был написан на C++, но теперь большая его часть написана на самом D (самостоятельное размещение). Бэкенд и оптимизаторы машинного кода основаны на компиляторе Symantec. Сначала он поддерживал только 32-битную x86, с добавлением поддержки для 64-битной amd64 и PowerPC Уолтером Брайтом. Позже бэкенд и почти весь компилятор были перенесены с C++ на D для полного самостоятельного размещения.
  • GCCGNU Compiler Collection , объединил GDC [45] с GCC 9 29 октября 2018 года. [46] Первые рабочие версии GDC с GCC, основанные на GCC 3.3 и GCC 3.4 на 32-битной архитектуре x86 в Linux и macOS [47], были выпущены 22 марта 2004 года. С тех пор GDC получил поддержку дополнительных платформ, улучшил производительность и исправил ошибки, одновременно отслеживая исходный код DMD для интерфейса и спецификации языка. [48]
  • LDC – Компилятор на основе DMD front-end, который использует LLVM в качестве своего компилятора back-end. Первая версия качества релиза была опубликована 9 января 2009 года. [49] Он поддерживает версию 2.0. [50]

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

  • Компилятор D для .NET – бэкэнд для компилятора языка программирования D 2.0. [51] [52] Он компилирует код в байт-код Common Intermediate Language (CIL), а не в машинный код. Затем CIL можно запустить через виртуальную машину Common Language Infrastructure (CLI) . Проект не обновлялся годами, и автор указал, что проект больше не активен.
  • SDC – The Snazzy D Compiler [53] использует пользовательский front-end и LLVM в качестве своего back-end компилятора. Он написан на D и использует планировщик для обработки разрешения символов, чтобы элегантно обрабатывать функции времени компиляции D. Этот компилятор в настоящее время поддерживает ограниченное подмножество языка. [54] [55]

Используя указанные выше компиляторы и наборы инструментов, можно компилировать программы на D для множества различных архитектур, включая IA-32 , 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.

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

Редакторы и интегрированные среды разработки (IDE), поддерживающие подсветку синтаксиса и частичное завершение кода для языка, включают SlickEdit , Emacs , vim , SciTE , Smultron , Zeus, [56] и Geany среди прочих. [57]

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

Существуют среды разработки D с открытым исходным кодом для Windows , некоторые из них написаны на D, например Poseidon, [70] D-IDE, [71] и Entice Designer. [72]

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

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

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

Примеры

Пример 1

Этот пример программы выводит свои аргументы командной строки. mainФункция является точкой входа программы D и argsпредставляет собой массив строк, представляющих аргументы командной строки. A stringв D — это массив символов, представленный как immutable(char)[].

импорт std.stdio : writefln ;  void main ( строка [] аргументы ) {    foreach ( i , arg ; args )    writefln ( "args[%d] = '%s'" , i , arg );  }

Оператор foreachможет выполнять итерацию по любой коллекции. В этом случае он создает последовательность индексов ( i) и значений ( arg) из массива args. Индекс iи значение argимеют свои типы, выведенные из типа массива args.

Пример 2

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

импорт std.stdio , std.algorithm , std.range , std.string ;    пустая основная () {   dstring [] [ dstring ] подпись2слова ;   foreach ( dchar [] w ; строки ( Файл ( "words.txt" ))) {     w = w . chomp (). toLower ();   неизменяемая сигнатура = w.dup.sort ( ) . release ( ) . idup ;    подпись2слова [ подпись ] ~ = w.idup ;   } foreach ( слова ; подпись2слова ) {    если ( слова . длина > 1 )    writeln ( слова.присоединиться ( "" ) ) ; }}
  1. signature2words— встроенный ассоциативный массив, который сопоставляет ключи dstring (32-бит / char) с массивами dstrings. Он похожdefaultdict(list) на .
  2. lines(File())возвращает строки лениво, с новой строкой. Затем его нужно скопировать с , idupчтобы получить строку, которая будет использоваться для значений ассоциативного массива ( idupсвойство массивов возвращает неизменяемый дубликат массива, что требуется, поскольку dstringтип на самом деле immutable(dchar)[]). Встроенные ассоциативные массивы требуют неизменяемых ключей.
  3. Оператор ~=добавляет новую строку dstring к значениям соответствующего динамического массива.
  4. toLower, joinи chompявляются строковыми функциями, которые D позволяет использовать с синтаксисом метода. Названия таких функций часто похожи на строковые методы Python. преобразует toLowerстроку в нижний регистр, join(" ")объединяет массив строк в одну строку, используя один пробел в качестве разделителя, и chompудаляет новую строку из конца строки, если она присутствует. w.dup.sort().release().idupболее читабельна, но эквивалентна, release(sort(w.dup)).idupнапример, . Эта функция называется UFCS (Uniform Function Call Syntax) и позволяет расширять любые встроенные или сторонние типы пакетов функциональностью, подобной методу. Стиль написания кода, подобный этому, часто называют конвейером ( особенно когда используемые объекты вычисляются лениво, например, итераторы/диапазоны) или интерфейсом Fluent .
  5. Это sortфункция std.algorithm, которая сортирует массив на месте, создавая уникальную сигнатуру для слов, которые являются анаграммами друг друга. release()Метод возвращаемого значения sort()удобен для сохранения кода в виде одного выражения.
  6. Второй foreachперебирает значения ассоциативного массива и может определить тип words.
  7. signatureприсваивается неизменяемой переменной, ее тип выводится.
  8. UTF-32 dchar[] используется вместо обычного UTF-8, char[] иначе sort()отказывается сортировать. Есть более эффективные способы написать эту программу, используя только UTF-8.

Использует

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

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

Печально известная северокорейская хакерская группа, известная как Lazarus, использовала уязвимость CVE-2021-44228, также известную как « Log4Shell », для развертывания трех семейств вредоносных программ, написанных на DLang. [90]

Критика

Отсутствие прозрачности, гибкости и предсказуемости в процессе исправления известных недостатков и ошибок, а также сложность внесения мелких и крупных изменений в язык D, неминуемо описаны в статье блога [91] бывшим участником. Описанное там явное разочарование привело к форку OpenD [92] 1 января 2024 года.

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

Ссылки

  1. ^ ab "D Change Log to Nov 7 2005". Язык программирования D 1.0 . Digital Mars . Получено 1 декабря 2011 .
  2. ^ "2.109.1" . Получено 7 июля 2024 г.
  3. ^ abc "dmd front end теперь переключен на лицензию Boost" . Получено 9 сентября 2014 г. .
  4. ^ abc "dmd Backend преобразован в лицензию 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. ^ "On: Show HN: A nice C string API". Hacker News . 3 декабря 2022 г. . Получено 4 декабря 2022 г. .
  9. ^ Александреску, Андрей (2010). Язык программирования D (Первое изд.). Аппер Сэддл Ривер, Нью-Джерси: Addison-Wesley. стр. 314. ISBN 978-0321635365.
  10. ^ "Создание assert() в Swift, часть 2: __FILE__ и __LINE__" . Получено 25 сентября 2014 г. .
  11. ^ "Введение - Язык программирования D". dlang.org . Получено 21 апреля 2024 г. .  В этой статье используется текст из этой свободной контентной работы. Лицензия BSL-1.0 (лицензионное заявление/разрешение).
  12. ^ «Строки D против строк C++». Digital Mars. 2012.
  13. ^ "D Complex Types and C++ std::complex". Digital Mars . 2012. Архивировано из оригинала 13 января 2008 г. Получено 4 ноября 2021 г.
  14. ^ "Expressions". Digital Mars . Получено 27 декабря 2012 г.
  15. ^ "std.gc". Язык программирования D 1.0 . Digital Mars . Получено 6 июля 2010 .
  16. ^ "Управление памятью". Язык программирования D 2.0 . Digital Mars . Получено 17 февраля 2012 г.
  17. ^ ab "Go Your Own Way (Part One: The Stack)". The D Blog . 7 июля 2017 . Получено 7 мая 2020 .
  18. ^ "Атрибуты - Язык программирования D". dlang.org . Получено 7 мая 2020 г. .
  19. ^ "std.experimental.allocator - D Programming Language". dlang.org . Получено 7 мая 2020 г. .
  20. ^ Бартош Милевски. "SafeD – D Programming Language" . Получено 17 июля 2014 г.
  21. ^ Стивен Швейгхоффер (28 сентября 2016 г.). «Как писать @trusted Code на языке D» . Получено 4 января 2018 г.
  22. ^ "Scoped Pointers". GitHub . 3 апреля 2020 г.
  23. ^ «Запечатанные ссылки».
  24. ^ «Спецификация языка D: Функции — Параметры области возврата».
  25. ^ «Владение и заимствование в D». 15 июля 2019 г.
  26. ^ «Спецификация языка D: Функции — Классы хранения параметров функций».
  27. ^ "PyD". GitHub . 7 мая 2020 . Получено 7 мая 2020 .
  28. ^ Паркер, Майк. "Пакет derelict-lua на DUB". Реестр пакетов DUB . Получено 7 мая 2020 г.
  29. ^ Паркер, Майк. "Пакет bindbc-lua в DUB". Реестр пакетов DUB . Получено 7 мая 2020 г.
  30. ^ «Лучше С».
  31. ^ "D Change Log". D Programming Language 1.0 . Digital Mars . Получено 11 января 2012 г.
  32. ^ "Введение". Язык программирования D 1.0 . Digital Mars . Получено 1 декабря 2011 г.
  33. ^ "Анонс новой библиотеки" . Получено 15 февраля 2012 г. .
  34. ^ "Wiki4D: Standard Lib" . Получено 6 июля 2010 г.
  35. ^ "Журнал изменений – Язык программирования D". Язык программирования D 2.0 . D Language Foundation . Получено 22 ноября 2020 г. .
  36. ^ "Tango для D2: Все пользовательские модули перенесены" . Получено 16 февраля 2012 г.
  37. ^ Уолтер Брайт. "Re: GitHub или dsource?" . Получено 15 февраля 2012 г. .
  38. ^ Андрей Александреску. "D1 будет прекращен 31 декабря 2012 года" . Получено 31 января 2014 года .
  39. ^ "D Change Log". D Programming Language 1.0 . Digital Mars . Получено 31 января 2014 г.
  40. ^ "backendlicense.txt". Исходный код DMD . GitHub. Архивировано из оригинала 22 октября 2016 г. Получено 5 марта 2012 г.
  41. ^ "Reddit comment by Walter Bright". 5 марта 2009 г. Получено 9 сентября 2014 г.
  42. ^ D-Compiler-unter-freier-Lizenz на linux-magazin.de (2017, на немецком языке)
  43. ^ переключить бэкэнд на лицензию Boost #6680 от Уолтера Брайта на github.com
  44. ^ D Язык принят для включения в GCC
  45. ^ "ГДК".
  46. ^ "GCC 9 Release Series — Changes, New Features, and Fixes - GNU Project - Free Software Foundation (FSF)". gcc.gnu.org . Получено 7 мая 2020 г. .
  47. ^ "Еще один фронтенд для GCC". forum.dlang.org . Получено 7 мая 2020 г. .
  48. ^ «Изменения, новые функции и исправления в серии релизов GCC 9».
  49. ^ "Проект компилятора LLVM D на GitHub". GitHub . Получено 19 августа 2016 .
  50. ^ "BuildInstructionsPhobosDruntimeTrunk – ldc – D Programming Language – Trac" . Получено 11 августа 2015 г. .
  51. ^ "D .NET project on CodePlex". Архивировано из оригинала 26 января 2018 года . Получено 3 июля 2010 года .
  52. ^ Джонатан Аллен (15 мая 2009 г.). «Исходный код компилятора D.NET теперь доступен». InfoQ . Получено 6 июля 2010 г.
  53. ^ "Make SDC the Snazzy D compiler". GitHub . Получено 24 сентября 2023 г.
  54. ^ DConf 2014: SDC, D Compiler as a Library от Amaury Sechet. YouTube . Получено 8 января 2014 г.Архивировано в Ghostarchive и Wayback Machine
  55. ^ "deadalnix/SDC". Гитхаб . Проверено 8 января 2014 г.
  56. ^ "Wiki4D: EditorSupport/ZeusForWindows" . Получено 11 августа 2015 г. .
  57. ^ "Wiki4D: Editor Support" . Получено 3 июля 2010 г. .
  58. ^ "Basile.B / dexed". GitLab . Получено 29 апреля 2020 г.
  59. ^ "Mono-D - D Wiki". wiki.dlang.org . Получено 30 апреля 2020 г. .
  60. ^ "Mono-D – D Support for MonoDevelop". Архивировано из оригинала 1 февраля 2012 года . Получено 11 августа 2015 года .
  61. ^ "Google Project Hosting" . Получено 11 августа 2015 г.
  62. ^ "descent" . Получено 11 августа 2015 .
  63. ^ "Visual D - D Programming Language" . Получено 11 августа 2015 г. .
  64. ^ Шютце, Райнер (17 апреля 2020 г.). "rainers/visuald: Visual D — расширение Visual Studio для языка программирования D". github.com . Получено 30 апреля 2020 г. .
  65. ^ "dlang-vscode". GitHub . Получено 21 декабря 2016 .
  66. ^ "code-d". GitHub . Получено 21 декабря 2016 .
  67. ^ "Мишель Фортин – D для Xcode" . Получено 11 августа 2015 г.
  68. ^ "Dav1dde/lumen". GitHub . Получено 11 августа 2015 г.
  69. ^ Майкл, Паркер (7 октября 2016 г.). "Project Highlight: DlangUI". The D Blog . Получено 12 сентября 2024 г. .
  70. ^ "poseidon" . Получено 11 августа 2015 г. .
  71. ^ "Mono-D – D Support for MonoDevelop" . Получено 11 августа 2015 г. .
  72. ^ "Entice Designer – Dprogramming.com – Язык программирования D" . Получено 11 августа 2015 г.
  73. ^ "Что такое DustMite?". GitHub . Получено 29 апреля 2020 г.
  74. ^ "dlang/dub: Система управления пакетами и сборками для D". GitHub . Получено 29 апреля 2020 г. .
  75. ^ "Under the Hood: warp, быстрый препроцессор C и C++". 28 марта 2014 г. Получено 4 января 2018 г.
  76. ^ "Более быстрые инструменты командной строки в D". 24 мая 2017 г. Получено 4 января 2018 г.
  77. ^ "Introducing Vectorflow". 2 августа 2017 г. Получено 4 января 2018 г.
  78. ^ "Quantum Break: AAA Gaming With Some D Code" . Получено 4 января 2018 г. .
  79. ^ "Виртуальная машина Higgs JavaScript". GitHub . Получено 4 января 2018 г.
  80. ^ "Реализация AD языка программирования ECMA 262 (Javascript)". GitHub . Получено 4 января 2018 г. .
  81. ^ "Project Highlight: The PowerNex Kernel". 24 июня 2016 г. Получено 4 января 2018 г.
  82. ^ "DCompute: Запуск D на GPU". 30 октября 2017 г. Получено 4 января 2018 г.
  83. ^ "vibe.d - высокопроизводительный асинхронный ввод-вывод, параллелизм и набор инструментов для веб-приложений, написанный на D" . Получено 4 января 2018 г. .
  84. ^ "Project Highlight: Diamond MVC Framework". 20 ноября 2017 г. Получено 4 января 2018 г.
  85. ^ "Числовой возраст для D: Mir GLAS быстрее, чем OpenBLAS и Eigen" . Получено 4 января 2018 г. .
  86. ^ "О Тиликсе и D: Интервью с Джеральдом Нанном". 11 августа 2017 г. Получено 4 января 2018 г.
  87. ^ "Project Highlight: DlangUI". 7 октября 2016 г. Получено 4 января 2018 г.
  88. ^ "Project Highlight: Funkwerk". 28 июля 2017 г. Получено 4 января 2018 г.
  89. ^ "Netflix/vectorflow". GitHub.com . Netflix, Inc. 5 мая 2020 г. . Получено 7 мая 2020 г. .
  90. ^ "Хакеры Lazarus выпустили новое вредоносное ПО RAT, используя двухлетнюю ошибку Log4j". 11 декабря 2023 г. Получено 11 декабря 2023 г.
  91. ^ "Отплыло судно, перевозящее столовое серебро" . Получено 6 мая 2024 г.
  92. ^ "Язык программирования OpenD" . Получено 14 мая 2024 г.

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

  • Александреску, Андрей (4 января 2010 г.). Язык программирования D (1-е изд.). Addison-Wesley Professional. ISBN 978-0-321-63536-5.
  • Александреску, Андрей (15 июня 2009 г.). «Дело Д». Журнал доктора Добба.
  • Брайт, Уолтер (8 апреля 2014 г.). «Как я пришел к написанию D». Журнал доктора Добба.
  • Чехрели, Али (1 февраля 2012 г.). «Программирование на языке D».(распространяется по лицензии CC-BY-NC-SA). Эта книга обучает программированию новичков, но также охватывает многие продвинутые темы D.
  • Метц, Кейд (7 июля 2014 г.). «Следующий большой язык программирования, о котором вы никогда не слышали». Wired .
  • Руппе, Адам (май 2014 г.). D Поваренная книга (1-е изд.). ПАКТ Издательство. ISBN 978-1-783-28721-5.
  • Официальный сайт
  • Цифровой Марс
  • Турецкий форум
  • Dlang на GitHub
Взято с "https://en.wikipedia.org/w/index.php?title=D_(язык_программирования)&oldid=1268587886"