| パラダイム | マルチパラダイム:関数型、命令型、オブジェクト指向 |
|---|---|
| デザイン: | ウォルター・ブライト、アンドレイ・アレクサンドルスク(2007 年以降) |
| 開発者 | D言語財団 |
| 初登場 | 2001年12月8日[1] |
| 安定リリース | 2.109.1 [2]
/ 2024年7月1日 |
| タイピングの規律 | 推測、静的、強い |
| OS | FreeBSD、Linux、macOS、Windows |
| ライセンス | ブースト[3] [4] [5] |
| ファイル名拡張子 | .d [6] [7] |
| Webサイト | dlang.org |
| 主な実装 | |
| DMD (リファレンス実装)、GCC、
GDC、 LDC、SDC | |
| 影響を受けた | |
| BASIC、[8] C、C++、C#、エッフェル、[9] Java、Python | |
| 影響を受けた | |
| Genie、MiniD、Qore、Swift、[10] Vala、C++11、C++14、C++17、C++20、Go、C#、その他 | |
Dはdlangとも呼ばれ、Digital MarsのWalter Brightによって作成され、2001 年にリリースされたマルチパラダイム システムプログラミング 言語です。2007 年にAndrei Alexandrescu が設計と開発の取り組みに参加しました。C ++のリエンジニアリングとして始まりましたが、D は現在ではまったく異なる言語です。開発が進むにつれて、他の高水準プログラミング言語からインスピレーションを得てきました。特に、 Java、Python、Ruby、C#、およびEiffelの影響を受けています。
D 言語リファレンスでは次のように説明されています。
D言語は、ネイティブコードにコンパイルされるC言語のような構文を持つ汎用システムプログラミング言語です。静的型付けされており、自動(ガベージコレクション)と手動のメモリ管理の両方をサポートしています。Dプログラムはモジュールとして構成されており、個別にコンパイルして外部ライブラリとリンクすることでネイティブライブラリまたは実行可能ファイルを作成できます。[11]
特徴
D は一般に C および C++ ソース コードとソース互換性がありません。ただし、C と D の両方で合法なコードは同じように動作するはずです。
C++ と同様に、D にはクロージャ、匿名関数、コンパイル時の関数実行、範囲、組み込みのコンテナ反復概念、および型推論があります。D の宣言、ステートメント、および式の構文もC++ のものとほぼ一致しています。
C++ とは異なり、D は契約による設計、モジュール、ガベージ コレクション、ファースト クラス 配列、配列のスライス、ネストされた関数、遅延評価も実装しています。D は、C++ スタイルの多重継承ではなく、インターフェイスとミックスインを使用したJava スタイルの単一継承を使用します。
D はシステム プログラミング言語です。C++ と同様、JavaやC#などのアプリケーション言語とは異なり、D はインライン アセンブラを含む低レベル プログラミングをサポートしています。インライン アセンブラを使用すると、プログラマーは標準の D コード内にマシン固有のアセンブリ コードを入力できます。システム プログラマーはこの方法を使用して、オペレーティング システムやデバイス ドライバーなど、基盤となるハードウェアと直接インターフェイスするプログラムを実行するために必要なプロセッサの低レベル機能にアクセスします。低レベル プログラミングは、コンパイラーによって生成されるコードよりも高性能なコードを書くためにも使用されます。
D は関数のオーバーロードと演算子のオーバーロードをサポートしています。シンボル (関数、変数、クラス) は任意の順序で宣言でき、前方宣言は必要ありません。
Dでは、テキスト文字列は文字の配列であり、Dの配列は境界チェックされます。[12] Dには複素数と虚数のためのファーストクラス型があります。 [13]
プログラミングパラダイム
D は 5 つの主要なプログラミングパラダイムをサポートしています。
命令形
D の命令型プログラミングは、C のものとほぼ同じです。関数、データ、ステートメント、宣言、式は C と同じように動作し、C ランタイム ライブラリに直接アクセスできます。一方、C とは異なり、D のforeachloop 構造ではコレクションをループできます。D では、ネストされた関数も使用できます。ネストされた関数とは、別の関数内で宣言され、囲んでいる関数のローカル変数にアクセスできる関数です。
std.stdioをインポートします。
void main () { int乗数= 10 ; int scaled ( int x ) { return x *乗数; }
foreach ( i ; 0 .. 10 ) { writefln ( "Hello, world %d! scaled = %d" , i , scaled ( i )); } }
オブジェクト指向
D のオブジェクト指向プログラミングは、すべてのクラスが Object クラスから派生した単一の継承階層に基づいています。D は多重継承をサポートしていません。代わりに、C++ の純粋な抽象クラスに相当する Java スタイルのインターフェースと、共通の機能を継承階層から分離するミックスインを使用します。D では、インターフェースで静的メソッドと最終メソッド (非仮想メソッド) を定義することもできます。
D のインターフェースと継承は、オーバーライドされたメソッドの戻り値の型に対して共変型をサポートします。
D は型転送とオプションのカスタム動的ディスパッチをサポートします。
D のクラス (およびインターフェース) には、契約による設計方法論に従って、パブリック メソッドに入る前と後に自動的にチェックされる不変条件を含めることができます。
クラス (および構造体) の多くの側面は、コンパイル時 (を使用したリフレクション プログラミング(リフレクション)の形式) および実行時 (RTTI / ) に自動的にイントロスペクトできるため、汎用コードや自動コード生成 (通常はコンパイル時の手法を使用) が容易になります。
type traitsTypeInfo
機能的
Dは関数リテラル、クロージャ、再帰的に不変なオブジェクト、高階関数の使用などの関数型プログラミング機能をサポートしています。匿名関数には、複数のステートメント形式と「省略形」の単一式表記の2つの構文があります。[14]
int function ( int ) g ; g = ( x ) { return x * x ; }; // ロングハンドg = ( x ) => x * x ; // ショートハンド
関数リテラルには 2 つの組み込み型があります。functionは、スタックに割り当てられた関数への単なるポインターで、 は、関連するスタック フレームdelegateへのポインターも含みます。スタック フレームは、現在のローカル変数を含む周囲の「環境」です。 型推論は匿名関数で使用できます。その場合、コンパイラは、環境ポインターが不要であることを証明できない限り、 を作成します。同様に、クロージャを実装するために、コンパイラは、必要な場合にのみ (たとえば、クロージャが別の関数によって返され、その関数のスコープから抜ける場合)、囲まれたローカル変数をヒープ上に配置します。 型推論を使用する場合、コンパイラは、適用可能であることを証明できれば、
やなどの属性も関数の型に追加します。delegatepurenothrow
カリー化や、 map、filter、およびReduceなどの一般的な高階関数などのその他の機能も、標準ライブラリ モジュールstd.functionalおよびを通じて利用できますstd.algorithm。
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 ) // 囲みスコープへの参照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: " , result ); // 結果: 15 }
あるいは、上記の関数構成は、より自然な左から右への読み取りのために、Uniform function call syntax (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).parallelUFCS を使用すると同等になりますstd.parallelism.parallel(iota(11))。
同じモジュールは、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 の場合:
* std.algorithm.reduce を使用する場合 5140 ミリ秒
* std.parallelism.taskPool.reduce を使用する場合 888 ミリ秒
*
* AMD Threadripper 2950X および gdc 9.3.0 の場合:
* std.algorithm.reduce を使用する場合 2864ミリ秒 *
std.parallelism.taskPool.reduce を使用する場合 95 ミリ秒
*/
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 ) { received ( // デリゲートはメッセージ タイプを一致させるために使用されます。( int msg ) => writeln ( "int received: " , msg ), ( Tid sender ) { cont = false ; sender . send (- 1 ); }, ( Variant v ) => writeln ( "huh?" ) // Variant は任意のタイプと一致します); } }
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) を送信
受信(( int x ) => writeln ( "メインスレッドがメッセージを受信しました: " , x )); }
メタプログラミング
メタプログラミングは、テンプレート、コンパイル時の関数実行、タプル、文字列ミックスインを通じてサポートされます。次の例は、D のコンパイル時の機能の一部を示しています。
D のテンプレートは、C++ のテンプレートの関数型スタイルに比べて、より命令型のスタイルで記述できます。これは、数値の 階乗を計算する通常の関数です。
ulong階乗( ulong n ) { if ( n < 2 ) return 1 ; else return n *階乗( n - 1 ); }
ここでは、D のコンパイル時条件構文である の使用法をstatic if示し、上記の関数と同様のコードを使用して同じ計算を実行するテンプレートを構築します。
テンプレートFactorial ( ulong n ) { static if ( n < 2 ) enum Factorial = 1 ; else enum Factorial = n * Factorial !( n - 1 ); }
次の 2 つの例では、上で定義したテンプレートと関数を使用して階乗を計算します。定数の型は、コンパイラが代入の右側から 型を推測するため、明示的に指定する必要はありません。
enum fact_7 =階乗!( 7 );
これはコンパイル時関数実行(CTFE)の例です。通常の関数は、特定の条件を満たしていれば、定数のコンパイル時式で使用できます。
列挙型fact_9 =階乗( 9 );
このstd.string.format関数は、printfのようなデータ フォーマット (CTFE を介してコンパイル時にも) を実行し、"msg"プラグマはコンパイル時に結果を表示します。
std.string : formatをインポートします。プラグマ( msg 、format ( "7! = %s" 、fact_7 ) );プラグマ( msg 、format ( "9! = %s" 、fact_9 ));
文字列ミックスインをコンパイル時の関数実行と組み合わせると、コンパイル時に文字列操作を使用して D コードを生成できます。これを使用して、プログラムの一部としてコンパイルされるドメイン固有言語を解析できます。
import FooToD ; // Foo ソースコードを解析し、同等の D コードを返す関数を含む仮想モジュールvoid main () { mixin ( fooToD ( import ( "example.foo" ))); }
メモリ管理
メモリは通常、ガベージ コレクションで管理されますが、特定のオブジェクトはスコープ外になるとすぐに終了されることがあります。これは、D で書かれたプログラムやライブラリの大部分が使用しているものです。
メモリレイアウトをより細かく制御し、パフォーマンスを向上させる必要がある場合は、オーバーロードされた演算子を使用するか、 Cのmalloc と free をnew直接呼び出すか、カスタムアロケータスキーム(フォールバック付きスタック、RAIIスタイルの割り当て、参照カウント、共有参照カウントなど)を実装することで、明示的なメモリ管理が可能です。ガベージコレクションは制御可能で、プログラマはコレクターによる監視対象からメモリ範囲を追加または除外したり、コレクターを無効または有効にしたり、世代別または完全なコレクションサイクルを強制したりできます。[15]マニュアルには、プログラムでガベージコレクションが不十分な場合に、さまざまな高度に最適化されたメモリ管理スキームを実装する方法の例が多数示されています。[16]
関数では、structインスタンスはデフォルトでスタック上に割り当てられ、classインスタンスはデフォルトでヒープ上に割り当てられます(クラスインスタンスへの参照のみがスタック上にあります)。ただし、これはクラスの場合は変更可能です。たとえば、標準ライブラリテンプレートを使用したりstd.typecons.scoped、new構造体の場合はを使用して値ベースの変数ではなくポインターに割り当てたりすることができます。[17]
関数では、静的配列(サイズがわかっている)はスタックに割り当てられます。動的配列の場合は、関数core.stdc.stdlib.alloca(C言語と同様alloca)を使用してスタックにメモリを割り当てることができます。返されたポインタは、スライスを使用して(型付きの)動的配列に使用(再キャスト)できます(ただし、配列のサイズ変更(追加を含む)は避ける必要があります。また、明らかな理由により、関数から返されてはいけません)。[17]
キーワードscopeはコードの一部に注釈を付けるだけでなく、変数やクラス/構造体にも使用でき、スコープの終了時にすぐに破棄(デストラクタの呼び出し)する必要があることを示すことができます。メモリが解放されるかどうかは、実装やクラスと構造体の違いによっても異なります。[18]
std.experimental.allocatorモジュール式で構成可能なアロケータテンプレートが含まれており、特殊なユースケース向けにカスタマイズされた高性能アロケータを作成できます。[19]
セーフD
SafeD [20]は、メモリ安全
であることが保証される D のサブセットに付けられた名前です。 マークされた関数は、@safeコンパイル時に、ポインタ演算やチェックされていないキャストなど、メモリの破損につながる可能性のある機能を使用していないことがチェックされます。呼び出される他の関数も、@safeまたはとしてマークする必要があります。関数は、SafeD で無効になっている機能の安全な使用と、メモリ破損の可能性のあるケースをコンパイラが区別できない場合に@trustedマークできます。 [21]@trusted
スコープの生涯安全性
当初は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 ); // エラー。p は gloin() をエスケープします。鼠径部( q ); // エラー。q は gloin() をエスケープします。鼠径部( r ); // r は gloin() をエスケープします。
return p ; // OK. return q ; // エラー、'scope' q を返すことができません。return r ; // OK. }
他のシステムとの相互作用
Cのアプリケーション バイナリ インターフェイス (ABI)と C のすべての基本型および派生型がサポートされているため、既存の C コードとライブラリに直接アクセスできます。Dバインディングは、多くの一般的な C ライブラリで使用できます。さらに、C の標準ライブラリは標準 D の一部です。
Microsoft Windows では、D はコンポーネント オブジェクト モデル(COM) コードにアクセスできます。
メモリ管理が適切に行われる限り、他の多くの言語を 1 つのバイナリで D と混在させることができます。たとえば、GDC コンパイラでは、C、C++、および Objective-C などのサポートされている他の言語コードをリンクして混在させることができます。D コード (関数) は、C、C++、Pascal ABI を使用しているとマークすることもでき、これらの言語で記述されたライブラリにコールバックとして渡すことができます。同様に、これらの言語で記述されたコード間では、双方向でデータを交換できます。これにより、通常はプリミティブ型、ポインタ、一部の形式の配列、共用体、構造体、および一部のタイプの関数ポインタのみに使用が制限されます。
他の多くのプログラミング言語では、拡張機能を書いたり言語のインタープリタを実行したりするためにC APIを提供していることが多いため、Dは標準のCバインディング(薄いDインターフェースファイルを使用)を使用して、これらの言語と直接インターフェースすることができます。たとえば、Python [27] 、Lua [28] [29]などの言語には双方向バインディングがあり、コンパイル時のコード生成やコンパイル時の型リフレクションメソッドを使用することがよくあります。
C++ コードとのやり取り
としてマークされた D コードの場合extern(C++)、次の機能が指定されます。
- 名前マングリング規則は、ターゲット上の C++ の規則と一致する必要があります。
- 関数呼び出しの場合、ABI は同等である必要があります。
- vtable は単一継承 (D 言語仕様でサポートされている唯一のレベル) まで一致する必要があります。
C++ 名前空間は、 namespace がC++ 名前空間の名前である
extern(C++, namespace)構文を介して使用されます。
C++相互運用の例
C++側
インポート<印刷> ;
クラスBase { public : virtual void print3i ( int a 、int b 、int c ) = 0 ; };
クラスDerived : public Base { public : int field ; Derived ( 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係数); };
int Derived::mul ( int factor ) { return field * factor ; }
派生* createInstance ( int i ) { return new Derived ( i ); }
void deleteInstance (派生*& d ) { delete d ; d = 0 ; }
Dサイド
extern ( C ++) {抽象クラスBase { void print3i ( int a , int b , int c ); }
クラスDerived : Base { intフィールド; @disable this (); override void print3i ( int a , int b , int c ); final int mul ( int factor ); }
派生createInstance ( int i ); void deleteInstance ( ref Derived d ); }
void main () { std.stdioをインポートします。
自動d1 = createInstance ( 5 ) ; writeln ( d1.field ) ; writeln ( d1.mul ( 4 ) ) ;
ベースb1 = d1 ; b1 . print3i ( 1 , 2 , 3 );
deleteInstance ( d1 );
assert ( d1はnull );
auto d2 = createInstance ( 42 ); writeln ( d2 .フィールド);
deleteInstance ( d2 );
assert ( d2はnull ); }
より良いC
Dプログラミング言語には「Better C」と呼ばれる公式サブセットがあります。[30]このサブセットは、C以外のランタイムライブラリの使用を必要とするD機能へのアクセスを禁止しています。
DMD および LDC ではコンパイラ フラグ「-betterC」、GDC では「-fno-druntime」によって有効にされ、Better Cは同じフラグでコンパイルされた D コード (および D 以外のリンクされたコード) のみを呼び出すことができますが、Better Cオプションなしでコンパイルされたコードは、Better C オプションを使用してコンパイルされたコードを呼び出すことができます。ただし、C と D がアサートを処理する方法が異なるため、動作が若干異なります。
Better Cに含まれる機能
- コンパイル時の機能の無制限の使用(たとえば、D の動的割り当て機能は、コンパイル時に D データを事前に割り当てるために使用できます)
- 完全なメタプログラミング機能
- ネストされた関数、ネストされた構造体、デリゲート、ラムダ
- メンバー関数、コンストラクタ、デストラクタ、操作オーバーロードなど。
- フルモジュールシステム
- 配列のスライスと配列境界のチェック
- RAII
- スコープ(終了)
- メモリの安全保護
- C++とのインターフェース
- COM クラスと C++ クラス
- アサート失敗はCランタイムライブラリに送られる
- 文字列付きスイッチ
- 最終スイッチ
- ユニットテストブロック
- printfフォーマット検証
Better Cから除外された機能
- ガベージコレクション
- TypeInfo と ModuleInfo
- 組み込みスレッド(例
core.thread) - 動的配列(静的配列のスライスは機能しますが)と連想配列
- 例外
- 同期され、
core.sync - 静的モジュールのコンストラクタまたはデストラクタ
歴史
ウォルター・ブライトは1999年に新しい言語の開発を始めました。Dは2001年12月に初めてリリースされ[1]、2007年1月にバージョン1.0に達しました[31] 。言語の最初のバージョン(D1)は、C++と同様に、命令型、オブジェクト指向、メタプログラミングパラダイムに重点を置いていました[32]。
Dコミュニティの一部のメンバーは、Dの公式ランタイムおよび標準ライブラリであるPhobosに不満を持ち、Tangoという代替ランタイムおよび標準ライブラリを作成しました。Tangoの最初の公式発表は、D 1.0のリリースから数日以内に行われました。[33] Tangoは、OOPと高度なモジュール性を取り入れた異なるプログラミングスタイルを採用しました。コミュニティ主導のプロジェクトであったため、Tangoは貢献に対してよりオープンであり、公式標準ライブラリよりも速く進歩することができました。当時、TangoとPhobosは、ランタイムサポートAPI(ガベージコレクター、スレッドサポートなど)が異なっていたため互換性がありませんでした。そのため、同じプロジェクトで両方のライブラリを使用することは不可能でした。どちらも広く使用されている2つのライブラリの存在は、一部のパッケージがPhobosを使用し、他のパッケージがTangoを使用することで、大きな論争を引き起こしました。[34]
2007年6月、D2の最初のバージョンがリリースされました。[35] D2の開発開始は、D1の安定化の兆しでした。言語の最初のバージョンはメンテナンス中であり、修正と実装のバグ修正のみが行われました。D2は、最初の実験的なconstシステムから始まり、言語に破壊的変更を導入しました。D2は後に、クロージャ、純粋性、関数型プログラミングパラダイムと並行プログラミングパラダイムのサポートなど、他の多くの言語機能を追加しました。D2は、ランタイムを標準ライブラリから分離することで、標準ライブラリの問題も解決しました。D2 Tangoポートの完了は、2012年2月に発表されました。[36]
2010 年 6 月 12 日にAndrei Alexandrescuの著書『The D Programming Language』が出版され、D2 が安定化しました。D2 は現在では単に「D」と呼ばれることが多いです。
2011年1月、Dの開発はバグトラッカー/パッチ提出ベースからGitHubに移行しました。これにより、コンパイラ、ランタイム、標準ライブラリへの貢献が大幅に増加しました。[37]
2011年12月、アンドレイ・アレクサンドレスクは、言語の最初のバージョンであるD1が2012年12月31日に廃止されることを発表しました。[38] D1の最終リリースであるD v1.076は、2012年12月31日にリリースされました。[39]
公式のDコンパイラであるWalter BrightによるDigital Mars Dコンパイラのコードは、もともとカスタムライセンスの下でリリースされ、ソースコードは利用可能ではあるもののオープンソースの定義には準拠していませんでした。[40] 2014年に、コンパイラのフロントエンドはBoost Software Licenseの下でオープンソースとして再ライセンスされました。[3]この再ライセンスされたコードには、Symantecで部分的に開発されていたバックエンドは含まれていませんでした。2017年4月7日、Symantecがバックエンドの再ライセンスも許可したことを受けて、コンパイラ全体がBoostライセンスの下で利用可能になりました。[4] [41] [42] [43] 2017年6月21日、D言語はGCCへの組み込みが承認されました。[44]
実装
現在の D 実装のほとんどは、マシン コードに直接コンパイルされます。
生産準備が整ったコンパイラ:
- DMD – Walter Bright によるDigital Mars D コンパイラは公式の D コンパイラであり、Boost Software Licenseの下でオープンソース化されています。[3] [4] DMD フロントエンドは、コンパイラ間の互換性を向上させるために、GDC (現在は GCC) と LDC で共有されています。当初、フロントエンドは C++ で書かれていましたが、現在ではその大部分が D 自身で書かれています (セルフホスティング)。バックエンドとマシンコード最適化プログラムは、Symantec コンパイラに基づいています。最初は 32 ビット x86 のみをサポートしていましたが、Walter Bright によって 64 ビット amd64 と PowerPC のサポートが追加されました。後に、バックエンドとほぼすべてのコンパイラが C++ から D に移植され、完全なセルフホスティングが可能になりました。
- GCC – GNUコンパイラコレクションは、2018年10月29日にGDC [45]をGCC 9に統合しました。 [46] LinuxおよびmacOS上の32ビットx86上のGCC 3.3およびGCC 3.4に基づくGCCを使用したGDCの最初の動作バージョン[47]は、2004年3月22日にリリースされました。それ以来、GDCは追加のプラットフォームのサポート、パフォーマンスの向上、バグの修正を獲得し、フロントエンドと言語仕様のアップストリームDMDコードを追跡してきました。[48]
- LDC – DMDフロントエンドをベースにしたコンパイラで、コンパイラバックエンドとしてLLVMを使用しています。最初のリリース品質バージョンは2009年1月9日に公開されました。 [49]バージョン2.0をサポートしています。[50]
おもちゃおよび概念実証コンパイラ:
- D Compiler for .NET – Dプログラミング言語2.0コンパイラのバックエンド。[51] [52]コードをマシンコードではなく共通中間言語(CIL)バイトコードにコンパイルします。CILは共通言語インフラストラクチャ(CLI)仮想マシンを介して実行できます。このプロジェクトは何年も更新されておらず、作者はプロジェクトがもうアクティブではないことを示しています。
- SDC – Snazzy Dコンパイラ[53]は、カスタムフロントエンドとLLVMをコンパイラバックエンドとして使用します。これはDで書かれており、Dのコンパイル時の機能をエレガントに処理するために、シンボル解決を処理するスケジューラを使用しています。このコンパイラは現在、言語の限られたサブセットをサポートしています。[54] [55]
上記のコンパイラとツールチェーンを使用すると、IA-32、amd64、AArch64、PowerPC、MIPS64、DEC Alpha、Motorola m68k、SPARC、s390、WebAssemblyなど、さまざまなアーキテクチャをターゲットとして D プログラムをコンパイルできます。サポートされている主なオペレーティングシステムはWindowsとLinuxですが、さまざまなコンパイラがMac OS X、FreeBSD、NetBSD、AIX、Solaris/OpenSolaris、Androidもホストまたはターゲットとして、またはその両方としてサポートしています。WebAssemblyターゲット (LDC および LLVM 経由でサポート) は、最新のウェブブラウザ ( Google Chrome、Mozilla Firefox、Microsoft Edge、Apple Safari ) や専用の Wasm 仮想マシン など、任意の WebAssembly 環境で動作できます。
開発ツール
この言語の構文強調表示と部分的なコード補完をサポートするエディタや統合開発環境(IDE)には、 SlickEdit、Emacs、vim、SciTE、Smultron、Zeus、[56]、Geanyなどがあります。[57]
- Dexed(旧Coedit)[58] 、 Object Pascalで書かれたDに特化したグラフィカルIDE
- Mono-D [59]は、主にCシャープで書かれた、 MonoDevelop / Xamarin Studioをベースにした機能豊富なクロスプラットフォームのDに重点を置いたグラフィカルIDEです。[60]
- D用のEclipseプラグインにはDDT [61]とDescent(廃止されたプロジェクト)[62]がある。
- Visual Studioとの統合はVisualDによって提供される。[63] [64]
- Dlang-Vscode [65]やCode-D [66]などの拡張機能を備えたVisual Studio Codeの統合。
- TextMate用のバンドルが利用可能であり、Code::Blocks IDE にはこの言語の部分的なサポートが含まれています。ただし、コード補完やリファクタリングなどの標準 IDE 機能はまだ利用できませんが、Code::Blocks では部分的に動作します (D は C に似ているため)。
- Xcode 3プラグイン「D for Xcode」はDベースのプロジェクトと開発を可能にします。[67]
- KDevelop(およびそのテキストエディタバックエンドであるKate)の自動補完プラグインが利用可能です。[68]
- Dlang IDEはDlangUIライブラリを使用してDで書かれたクロスプラットフォームIDEです。[69]
Windows用のオープンソースD IDEが存在し、その中にはPoseidon [70] 、 D-IDE [71]、Entice Designer [72]などDで書かれたものもあります。
D アプリケーションは、 GNU デバッガー(GDB) やWinDbgなどの任意の C/C++ デバッガーを使用してデバッグできますが、さまざまな D 固有の言語機能のサポートは非常に制限されています。Windows では、cv2pdb を使用してデバッグ情報を変換した後、Ddbg、または Microsoft デバッグ ツール (WinDBG および Visual Studio) を使用して D プログラムをデバッグできます。Linux 用の ZeroBUGS デバッガーは、D言語を実験的にサポートしています。Ddbg は、さまざまな IDE またはコマンド ラインから使用できます。ZeroBUGS には独自のグラフィカル ユーザー インターフェイス(GUI) があります。
DustMiteはDソースコードを最小限に抑えるツールであり、コンパイラやテストの問題を見つけるのに役立ちます。[73]
dubはDアプリケーションやライブラリ用の人気のパッケージおよびビルドマネージャであり、IDEサポートに統合されることが多い。[74]
例
例1
このサンプル プログラムは、コマンド ライン引数を出力します。main関数は D プログラムのエントリ ポイントであり、argsコマンド ライン引数を表す文字列の配列です。Dstringの A は、 で表される文字の配列ですimmutable(char)[]。
std.stdioをインポートします: writefln ;
void main (文字列[]引数) {
foreach ( i 、引数;引数)
writefln ( "args[%d] = '%s'" , i , arg );
}
このforeach文は、任意のコレクションを反復処理できます。この場合、配列からインデックス ( i) と値 ( ) のシーケンスを生成しています。インデックスと値の型は、配列の型から推論されます。
argargsiargargs
例2
次の例は、短いプログラムで D の機能と D の設計のトレードオフをいくつか示しています。これは、words.txt各行に異なる単語が含まれる というテキスト ファイルの行を反復処理し、他の単語のアナグラムであるすべての単語を出力します。
std.stdio 、std.algorithm 、std.range 、std.stringをインポートします。
void main () {
dstring [] [ dstring ]署名2単語;
foreach ( dchar [] w ;行(ファイル( "words.txt" ))) {
w = w .chomp ( ). toLower ();
不変シグネチャ= w . dup . sort (). release (). idup ;
signature2words [署名] ~= w . idup ;
}
foreach (単語;署名2単語) {
if (単語数.長さ> 1 )
writeln (単語. join ( " " ));
}
}
signature2wordsは、dstring (32 ビット / 文字) キーを dstring の配列にマッピングする組み込みの連想配列です。これは、Pythondefaultdict(list)の に似ています。lines(File())は、改行を含む行を遅延生成します。その後、idup連想配列の値に使用する文字列を取得するために、 でコピーする必要があります (idup配列の プロパティは、配列の不変の複製を返しますが、これは、dstring型が実際にはであるため必要ですimmutable(dchar)[])。組み込みの連想配列には、不変のキーが必要です。- 演算子
~=は、関連する動的配列の値に新しい dstring を追加します。 toLower、joinおよび は、chompD がメソッド構文で使用できる文字列関数です。このような関数の名前は、多くの場合 Python の文字列メソッドに似ています。 はtoLower、文字列を小文字に変換し、join(" ")単一のスペースを区切り文字として使用して文字列の配列を単一の文字列に結合し、chomp文字列の末尾に改行がある場合はそれを削除します。 はw.dup.sort().release().idupより読みやすくなっていますが、release(sort(w.dup)).idupたとえば と同等です。この機能は UFCS (Uniform Function Call Syntax) と呼ばれ、組み込みまたはサードパーティのパッケージ タイプをメソッドのような機能で拡張できます。このようなコードの記述スタイルは、パイプライン(特に、反復子や範囲など、使用されるオブジェクトが遅延計算される場合) またはFluent インターフェイスと呼ばれることがよくあります。- は
sort、配列をその場でソートし、互いにアナグラムになっている単語に固有の署名を作成する std.algorithm 関数です。release()の戻り値の メソッドは、sort()コードを単一の式として保持するのに便利です。 - 2 番目は
foreach連想配列の値を反復処理し、 の型を推測できますwords。 signature不変変数に割り当てられる場合、その型は推論されます。- 通常のUTF-8
dchar[]の代わりにUTF-32が使用され、そうでない場合はソートが拒否されます。このプログラムを UTF-8 のみを使用して記述するより効率的な方法があります。char[]sort()
用途
Dプログラミング言語をプロジェクトに使用している著名な組織としては、Facebook、[75]、 eBay、[76]、Netflix [77]などが挙げられます。
DはAAAゲーム、[78]言語インタープリタ、仮想マシン、[79] [80]オペレーティングシステム カーネル、[81] GPUプログラミング、[82] Web開発、[83] [84] 数値解析、[85] GUIアプリケーション、[86] [87]乗客情報システム、[ 88]機械学習、[89]テキスト処理、Webおよびアプリケーションサーバー、研究などに効果的に使用されています。
Lazarusとして知られる悪名高い北朝鮮のハッキンググループは、CVE-2021-44228、別名「Log4Shell」を悪用して、DLangで書かれた3つのマルウェアファミリを展開しました。[90]
批評
既知の欠陥やエラーの修正を組み込むプロセスにおける透明性、俊敏性、予測可能性の欠如、およびD言語に小さな変更や大きな変更を導入することの難しさは、元貢献者によるブログ記事[91]ですぐに説明されています。そこで説明された明らかなフラストレーションは、2024年1月1日の OpenDフォーク[92]につながりました。
参照
参考文献
- ^ ab 「2005 年 11 月 7 日までの D 変更ログ」。Dプログラミング言語 1.0。Digital Mars。2011年12 月 1 日閲覧。
- ^ “2.109.1” . 2024年7月7日閲覧。
- ^ abc 「dmdフロントエンドがBoostライセンスに切り替わりました」。2014年9月9日閲覧。
- ^ abc 「dmdバックエンドがBoostライセンスに変換されました」。2017年4月7日。 2017年4月9日閲覧。
- ^ 「D 2.0 FAQ」 。 2015年8月11日閲覧。
- ^ 「Dプログラミング言語 - Fileinfo.com」。2020年11月15日閲覧。 [要出典]
- ^ 「Dプログラミング言語 - dlang.org」。2020年11月15日閲覧。[要出典]
- ^ 「On: Show HN: 素晴らしい C 文字列 API」. Hacker News . 2022 年 12 月 3 日. 2022 年12 月 4 日閲覧。
- ^ Alexandrescu, Andrei (2010). Dプログラミング言語(初版). アッパーサドルリバー、ニュージャージー:Addison-Wesley. p. 314. ISBN 978-0321635365。
- ^ 「Swift で assert() を構築する、パート 2: __FILE__ と __LINE__」 。 2014 年9 月 25 日閲覧。
- ^ 「Introduction - D Programming Language」. dlang.org . 2024年4月21日閲覧。
この記事には、この無料コンテンツ作品のテキストが組み込まれています。BSL-1.0 (ライセンス ステートメント/許可) に基づいてライセンスされています。
- ^ 「D 文字列と C++ 文字列」。Digital Mars。2012 年。
- ^ 「D Complex Types and C++ std::complex」。Digital Mars。2012年。2008年1月13日時点のオリジナルよりアーカイブ。 2021年11月4日閲覧。
- ^ 「Expressions」。Digital Mars 。 2012年12月27日閲覧。
- ^ "std.gc". Dプログラミング言語1.0 . Digital Mars . 2010年7月6日閲覧。
- ^ 「メモリ管理」。Dプログラミング言語2.0。Digital Mars 。 2012年2月17日閲覧。
- ^ ab 「Go Your Own Way (Part One: The Stack)」。The D Blog。2017年7月7日。 2020年5月7日閲覧。
- ^ 「属性 - Dプログラミング言語」dlang.org . 2020年5月7日閲覧。
- ^ 「std.experimental.allocator - Dプログラミング言語」dlang.org . 2020年5月7日閲覧。
- ^ Bartosz Milewski. 「SafeD – Dプログラミング言語」 . 2014年7月17日閲覧。
- ^ Steven Schveighoffer (2016 年 9 月 28 日). 「D で @trusted コードの書き方」 . 2018 年1 月 4 日閲覧。
- ^ 「スコープ付きポインタ」。GitHub 。 2020年4月3日。
- ^ 「封印された参照」。
- ^ 「D言語仕様: 関数 - スコープパラメータを返す」。
- ^ 「Dにおける所有権と借入」。2019年7月15日。
- ^ 「D言語仕様: 関数 - 関数パラメータ記憶クラス」。
- ^ “PyD”. GitHub . 2020年5月7日. 2020年5月7日閲覧。
- ^ Parker, Mike. 「DUB のパッケージ derelict-lua」。DUBパッケージ レジストリ。2020年5 月 7 日閲覧。
- ^ Parker, Mike. 「DUB のパッケージ bindbc-lua」。DUBパッケージ レジストリ。2020年5 月 7 日閲覧。
- ^ 「より良いC」。
- ^ 「D 変更ログ」。Dプログラミング言語 1.0。Digital Mars。2012年1 月 11 日閲覧。
- ^ 「Intro」。Dプログラミング言語1.0。Digital Mars 。 2011年12月1日閲覧。
- ^ 「新しいライブラリの発表」。2012年2月15日閲覧。
- ^ 「Wiki4D: 標準ライブラリ」 。 2010年7月6日閲覧。
- ^ 「変更ログ – Dプログラミング言語」。Dプログラミング言語2.0。D言語財団。 2020年11月22日閲覧。
- ^ 「Tango for D2: すべてのユーザーモジュールが移植されました」。2012年2月16日閲覧。
- ^ Walter Bright. 「Re: GitHub か dsource?」2012 年2 月 15 日閲覧。
- ^ Andrei Alexandrescu. 「D1は2012年12月31日に廃止される」 。 2014年1月31日閲覧。
- ^ 「D 変更ログ」。Dプログラミング言語 1.0。Digital Mars。2014年1 月 31 日閲覧。
- ^ "backendlicense.txt". DMD ソースコード. GitHub. 2016年10月22日時点のオリジナルよりアーカイブ。2012年3月5日閲覧。
- ^ 「Walter BrightによるRedditコメント」2009年3月5日。 2014年9月9日閲覧。
- ^ D-Compiler-unter-freier-Lizenz、linux-magazin.de (2017、ドイツ語)
- ^ バックエンドを Boost ライセンス #6680 に切り替える (Walter Bright より、github.com)
- ^ D GCCへの組み込みが承認された言語
- ^ 「GDC」.
- ^ 「GCC 9 リリースシリーズ — 変更点、新機能、修正 - GNU プロジェクト - フリーソフトウェア財団 (FSF)」。gcc.gnu.org 。2020年5 月 7 日閲覧。
- ^ 「GCC のもう一つのフロントエンド」。forum.dlang.org 。2020年5 月 7 日閲覧。
- ^ 「GCC 9 リリース シリーズの変更点、新機能、および修正点」。
- ^ 「 GitHub上の LLVM D コンパイラ プロジェクト」。GitHub。2016年8 月 19 日閲覧。
- ^ 「BuildInstructionsPhobosDruntimeTrunk – ldc – Dプログラミング言語 – Trac」 。 2015年8月11日閲覧。
- ^ 「CodePlex の D .NET プロジェクト」。2018 年 1 月 26 日時点のオリジナルよりアーカイブ。2010 年7 月 3 日閲覧。
- ^ Jonathan Allen (2009 年 5 月 15 日)。「D.NET コンパイラのソースが利用可能になりました」。InfoQ。2010年7 月 6 日閲覧。
- ^ 「SDC を Snazzy D コンパイラにする」GitHub 。2023年9 月 24 日閲覧。
- ^ DConf 2014: SDC、ライブラリとしてのDコンパイラ、Amaury Sechet著。YouTube 。 2014年1月8日閲覧。Ghostarchive と Wayback Machine にアーカイブされています
- ^ “デッドルニクス/SDC”. GitHub。2014 年1 月 8 日に取得。
- ^ 「Wiki4D: EditorSupport/ZeusForWindows」。2015年8月11日閲覧。
- ^ 「Wiki4D: エディターサポート」 。 2010年7月3日閲覧。
- ^ 「Basile.B / dexed」。GitLab 。 2020年4月29日閲覧。
- ^ 「Mono-D - D Wiki」. wiki.dlang.org . 2020年4月30日閲覧。
- ^ 「Mono-D – MonoDevelop の D サポート」。2012 年 2 月 1 日時点のオリジナルよりアーカイブ。2015 年8 月 11 日閲覧。
- ^ 「Google プロジェクト ホスティング」 。2015年8 月 11 日閲覧。
- ^ 「descent」 。 2015年8月11日閲覧。
- ^ 「Visual D - Dプログラミング言語」。2015年8月11日閲覧。
- ^ Schuetze, Rainer (2020年4月17日). 「rainers/visuald: Visual D - Visual Studio extension for the D programming language」. github.com . 2020年4月30日閲覧。
- ^ 「dlang-vscode」。GitHub 。 2016年12月21日閲覧。
- ^ "code-d". GitHub . 2016年12月21日閲覧。
- ^ 「Michel Fortin – D for Xcode」 。 2015年8月11日閲覧。
- ^ 「Dav1dde/lumen」。GitHub 。 2015年8月11日閲覧。
- ^ Michael, Parker (2016年10月7日). 「プロジェクトハイライト: DlangUI」. The D Blog . 2024年9月12日閲覧。
{{cite web}}: CS1 maint: url-status (リンク) - ^ 「ポセイドン」。2015年8月11日閲覧。
- ^ 「Mono-D – MonoDevelop の D サポート」 。2015年8 月 11 日閲覧。
- ^ 「Entice Designer – Dprogramming.com – Dプログラミング言語」 。 2015年8月11日閲覧。
- ^ 「DustMite とは何か?」GitHub 。2020年4 月 29 日閲覧。
- ^ 「 dlang/dub: D 用のパッケージおよびビルド管理システム」。GitHub。2020年4 月 29 日閲覧。
- ^ 「Under the Hood: warp、高速な C および C++ プリプロセッサ」。2014 年 3 月 28 日。2018年1 月 4 日閲覧。
- ^ 「D のより高速なコマンドラインツール」 2017 年 5 月 24 日。 2018 年1 月 4 日閲覧。
- ^ 「Vectorflow の紹介」。2017 年 8 月 2 日。2018年1 月 4 日閲覧。
- ^ 「Quantum Break: Dコードを使ったAAAゲーム」 。 2018年1月4日閲覧。
- ^ 「Higgs JavaScript 仮想マシン」。GitHub。2018年1月 4 日閲覧。
- ^ 「ECMA 262 (Javascript) プログラミング言語の AD 実装」。GitHub。2018年1月 4 日閲覧。
- ^ 「プロジェクトハイライト: PowerNexカーネル」。2016年6月24日。 2018年1月4日閲覧。
- ^ 「DCompute: GPU 上で D を実行する」。2017 年 10 月 30 日。2018 年1 月 4 日閲覧。
- ^ 「vibe.d - D で書かれた、高性能な非同期 I/O、並行性、Web アプリケーション ツールキット」 。2018年1 月 4 日閲覧。
- ^ 「プロジェクトハイライト: Diamond MVC フレームワーク」。2017 年 11 月 20 日。2018 年1 月 4 日閲覧。
- ^ 「Dの数値年齢:Mir GLASはOpenBLASやEigenよりも高速」 。 2018年1月4日閲覧。
- ^ 「TilixとDについて:ジェラルド・ナン氏へのインタビュー」2017年8月11日。 2018年1月4日閲覧。
- ^ 「プロジェクトハイライト: DlangUI」。2016年10月7日。 2018年1月4日閲覧。
- ^ 「プロジェクトハイライト:Funkwerk」。2017年7月28日。 2018年1月4日閲覧。
- ^ “Netflix/vectorflow”. GitHub.com . Netflix, Inc. 2020年5月5日. 2020年5月7日閲覧。
- ^ 「Lazarusハッカーが2年前のLog4jバグを利用して新たなRATマルウェアを投入」2023年12月11日。 2023年12月11日閲覧。
- ^ 「銀食器を積んだ船が出航した」。2024年5月6日閲覧。
- ^ 「OpenDプログラミング言語」 。 2024年5月14日閲覧。
さらに読む
- Alexandrescu, Andrei (2010 年 1 月 4 日)。プログラミング言語 D (第 1 版) 。Addison -Wesley Professional。ISBN 978-0-321-63536-5。
- アレクサンドルスク、アンドレイ(2009年6月15日)。 「Dの場合」。ドブ博士の日記。
- ブライト、ウォルター (2014 年 4 月 8 日)。「D を書くようになった経緯」。ドクター・ドブの日記。
- Çehreli, Ali (2012 年 2 月 1 日)。「D でのプログラミング」。(CC-BY-NC-SA ライセンスに基づいて配布) この本は初心者にプログラミングを教えますが、高度な D トピックも多数取り上げています。
- Metz, Cade (2014 年 7 月 7 日)。「聞いたことのない次世代のプログラミング言語」。Wired。
- ルッペ、アダム(2014年5月)。Dクックブック(第1版)。PACKT出版。ISBN 978-1-783-28721-5。
外部リンク
- 公式サイト
- デジタル火星
- トルコフォーラム
- GitHubの Dlang
