世界を動かす技術を、日本語で。

Dプログラミング言語

概要

D言語公式ページのバグ報告や改善方法、D言語の特徴とその利点を解説。 D言語の型推論、自動メモリ管理、配列やレンジサポートの紹介。 多様なプログラミングパラダイムと並行処理への対応力。 ネイティブコードへの高速コンパイルと安全性のバランス。 D Language Foundationの支援方法も案内。

バグ報告・ページ改善方法

  • ページの問題発見時は Bugzillaバグ報告
  • 内容の改善は GitHubアカウントオンライン編集・プルリクエスト送信
  • 小規模な修正向け、 大規模変更時はローカルクローン推奨
  • コード例は digitalmars.D forum へ投稿、承認後にランダム掲載
  • D Language Foundationの活動支援、 501(c)(3)非営利団体

D Programming Languageの特徴

  • 静的型付けシステムレベルアクセスCライク構文
  • 速く書けて、速く読めて、速く動く 設計思想
  • IDEやエディタ向けに linting・フォーマット・補完 設定可能
    • run.dlang.io でDコードの実験・動作確認

書きやすさと型推論

  • 型推論(auto) により冗長な型指定不要
    • 動的言語の利便性と静的言語の安全性を両立
  • 自動メモリ管理で 安全性・簡潔性・堅牢性 を確保
    • RAIIイディオムscope文 によるトランザクション的コード
  • 線形配列・連想配列・スライス・レンジ の組み込みサポート

モダンなパラダイムと設計力

  • クラシックな多態性・値セマンティクス・関数型・ジェネリクス など多彩なパラダイム
  • 契約プログラミング構造体・クラス・インターフェース サポート
  • イミュータブルデータ・メッセージパッシング・デフォルト非共有 による並行処理
  • ユニットテスト・情報隠蔽・高速コンパイル・明確なインターフェース

ネイティブ効率と安全性の両立

  • 効率的なネイティブコード への自然なコンパイル
  • 型安全性 を逸脱する必要がある場合は ポインタ・型キャスト・C関数アクセス 可能
    • 手動メモリ管理・カスタムアロケータ・インラインアセンブリ も利用可能
  • @safe, @trusted, @system 属性による 安全性と効率性のトレードオフ 管理
  • コンパイラによる 一貫性チェック

D Language Foundationとコミュニティ支援

  • D言語発展のための ボランティアとFoundationの協調
  • 寄付や支援 によるコミュニティ拡大と開発促進
  • 著作権: D Language Foundation (1999-2026)

Hackerたちの意見

余談だけど、昔のアンドレイ・アレクサンドレスクのC++プログラミング本は読むのが楽しかったな。特に「モダンC++デザイン」は最高だった。あと、このプレゼンテーションもね。https://accu.org/conf-docs/PDFs_2007/Alexandrescu-Choose_You... たくさんの無駄な議論をなくしてくれたよ!

個人的にはDやその後のNimにもっとワクワクしてたけど、結局はRustとZigが受け入れられたね。ため息。

Dの人気がRustに比べて低いことを嘆いてる人をよく見るけど、実はDにはずっと興味があったんだ。Rustのやってることが好きだから。でも、深く掘り下げる時間がなかったし、誰かに興味をそそられたいな。Rustが流行った理由やDがそうじゃなかった理由って技術的なものがあるの?DがRustに対して持ってる利点(その逆も)って何?

DとRustの企業の取り組み方が違うって感じかな。DはFacebookとRemedy Gamesがちょっと触ったくらいだし。多くの人がシステムプログラミングには自動メモリ管理が必要だと思ってるから、DはRustよりもその点で優れてるよ。GCに対する恐怖感もあって、全てのGCが同じじゃないってことを理解してない人が多いし、シナリオに応じてmalloc()/free()の実装を選ぶのと同じように、GCの実装方法もいろいろある。GCがあっても値型やスタック、グローバルメモリの割り当てができるからね。Dはコンパイル時のリフレクションがあって、コンパイル時メタプログラミングはRustのマクロよりずっと使いやすいし、コンパイル時実行もできる。コンパイル時間も!まるでTurbo PascalやDelphiを使ってるみたいだよ。言語の機能はC++に似てるのにね。複雑さが遅いコンパイルを意味しないってまた一つの証明だよ。私にとっては、C#やSwiftが仕事でDの代わりに使うことになったけど、主にその言語の背後にいる人たちの影響で、Dを選ぶことはなかったな。自分が知ってるスタックを持ってる人になりたくないから。

DとRustはメモリ安全性の扱い方が真逆だよね。Rustは高度なコンパイル時チェックで常にメモリについて考えさせることで安全性を確保してる。一方でDは、GCを使ってほぼ全てのメモリ安全性の懸念を忘れるか、ブロックスコープのオプトアウトでカウボーイスタイルの手動メモリ管理を選べる。Dはオブジェクト指向プログラミングを維持しつつ、関数型プログラミングも可能だけど、Rustは関数型プログラミング専用に設計されていて、従来の意味でのOOPは許可されてない。Dを数ヶ月使ってみて、C/C++のコードをDに移植するのはほぼ簡単だと気づいたよ。ほとんど同じセマンティクスに基づいてるからね。Rustだと、コードを移植するのに全体をゼロから考え直す必要があることが多い。

3つの理由があると思う。1. Dは初期にPython 2と3のようにGCの有無で分裂したけど(実質的に2つの標準ライブラリがあった)、Pythonのようにそれを耐えられる大きなコミュニティがなかった。2. 大きな支援がなかった。RustはMozillaの支援があってFirefoxとの統合があるから大きな違いがある。3. Dは十分に違いがなかった。自分の言語というより「C++をより良くしたもの」って感じがしたけど、C++は主にCのスーパーセットだから「クラス付きC」スタイルの移行はできなかった。

Rustが流行った理由やDがそうじゃなかった理由って技術的なものがあるの? うん。Dは「ガーベジコレクションを使ったシステムプログラミング」という死にかけた馬に乗ろうとしたけど、結果は予想通りだったよ。(そういう無駄なことを求めてる人はすでにGoやJavaを持ってるから、Dは必要ないんだ。)

Dの特徴の一つで、他の言語にも取り入れてほしいなと思うのは、メタプログラミングやコンパイル時のコード評価機能なんだよね(Rustについてはどうかわからないけど、同じような機能があったら、もっと真剣にチェックする理由になるかも)。コンパイル時にほとんどの言語を使えるっていうのがあって、ソースコードを生成する関数まであって、それがコンパイルプロセスの一部として扱われるんだ。もちろん、どの言語でもビルドプロセスの一部としてコード生成はできるけど、それはちょっと面倒だったり(しかも一つのプロジェクトに限られがち)。

Rustが成功してDがダメだった技術的な理由ってあるの?私の(ちょっと古い)経験から言うと、DはC++よりも良くてエレガントに感じる。Rustは確かにCやC++から影響を受けてるけど、ML系の言語からも多くのインスピレーションを得ていて、その結果としてタイプシステムがかなり強力になってる。

Rustが成功してDがダメだった技術的な理由ってあるの?当時、次のビッグな言語になる可能性があったと考えていた者として、私の記憶では、全体のエコシステムがあまりにも混乱していて、長期的に基盤として使うには安定性が足りなかったと思う。いくつかの例を挙げると: * コンパイラの状況:公式コンパイラはまだFOSSじゃなかったし、他のコンパイラも利用できなかったか、少なくとも使えなかった。FOSSへの移行は遅すぎたし、GCCのサポートも成熟するのに時間がかかりすぎた。 * Dのバージョン1とバージョン2の問題 * PhobosとTangoの標準ライブラリの問題 * GCありとGCなしの問題 これはD自体やそのガバナンスに対する判断ではないよ。私はDがとても良い言語だと思っていて、単にプロジェクトが広く採用されるための人手や商業的な支援が足りなかっただけだと思う。Facebookが採用したときはちょっと期待があったけど、残念ながら、あまり定着しなかったみたい。

DはRustに比べてメタプログラミングがずっと優れてる。これがまだDのプログラムを少し書き続けている唯一の理由の一つだよ。コンパイル時に型のイントロスペクションを行って、他の要素から型や関数を生成できるから、Rustの構文木を解析して操作するコンパイラプラグインを作る必要がないんだ。Rustには代数データ型みたいな関数型プログラミングの良さもあるけど、Dにはそれが欠けてるんだよね。

Rustが流行った理由とDが流行らなかった理由は技術的なものなの?このトークがその理由を説明してるけど、技術的なことじゃないよ: https://www.youtube.com/watch?v=XZ3w_jec1v8 > DのRustに対する利点は何?(その逆も含めて)Dの利点: ビルドが速い、典型的なプログラムでは約20のパッケージが必要で、100ではない、COMオブジェクト、簡単なメタプログラミング、3つのコンパイラ。GC、スクリプトにめっちゃ向いてる。Rustの利点: 借用チェッカーが優れてる。rustup。

学生の頃、私たちのグループはCS2*の授業でC++の代わりにD言語を使わざるを得なかったんだ。それが2009年のこと。16年経ってもその採用率は全然変わってないね。

採用については、そこまで心配する必要はないと思う。だって、DはGCCやClangにサポートされていて、継続的にメンテナンスされてるし、もし将来的にアップデートが止まったとしても、CやJavaなどを少しでも知ってる人なら簡単に自分の好きな言語に移植できるから。しかも、Dの構文は多くのコンパイル言語よりも表現力があって、ライブラリも機能が豊富でかなり整理されてるし、私にとっては使うのが楽しい言語なんだよね。

GCCはメンテナンスする人がいないとフロントエンドを落としちゃうことがあるけど、gcjでもそれが起こったし、gccgoもそろそろ同じ運命になるんじゃないかと思ってる。Go 1.18以降、ほとんどアップデートがないからね。チームはかなり小さくてほとんどボランティアだから、Walter Brightがどれだけ続けられるか、彼がバトンを渡した後に誰が続けるのかが心配だよ。

LLVMバックエンドのLDCがあって、これはLLVMプロジェクト/Clangとは別物だよ。

Dは全体的に好きなんだけど、WASMではRustやZig、さらにはGoみたいな他の言語に遅れを取ってるんだ。公式の理由は、WASMランタイムからのGCサポートを待ってるってことが多いけど、他のGC言語は自分たちのGCをそのまま搭載して進んでるみたい。

OpenDはほぼ完全な(例外をキャッチしたりスレッドを生成したりはできないから完全ではないけど、GCとかはちゃんと動く)wasmサポートを追加したんだけど、作業時間は一日もかからなかったと思う。とはいえ、wasmはクソだね、ほんとに悲惨なプラットフォームだよ。

Dが他の言語にはできないことって何?新しいスタッフエンジニアやテックリードの仕事を始めるとしたら、どうやってCTOを納得させてチームにDを学ばせる?逆に、年収200kのDのポジションはどこにあるの?2ヶ月で面接を取ってくれたら、週10時間Dを学ぶ時間を作るよ。

うーん、眼鏡に例えるといいかな。眼鏡をかけない人には納得させられないし、必要な人には納得させる必要もないからね。

個人的には、DはコアのGCでちょっと的外れだったと思う。C++の代わりが必要だった時期にリリースされたけど、その名からも分かるように、そういうポジションを狙ってたんだよね。でも、GCやランタイムを含めたことで、C#やJavaと同じカテゴリーになっちゃって、ランタイムとGCを使うのがOKなら、そっちの方が全然いい選択肢だし。結局、Goがこのスペースをさらに埋めちゃったしね。一方でC/C++の代替品としては、Rustが出てくるまで信頼できるものはなかったし、今ではZigがDが目指してたものをもっと勢いを持って実現してると思う。彼らの進む方向にはちょっとムカついてるけど、もっと早くC++の代替があったかもしれないのに。昔、この言語にワクワクしてたのを思い出すよ :D

FIl-C、新しいメモリ安全なC/C++コンパイラは、GCを導入することでそれを実現したから、振り返ってみるとDはちょっと誤解されてた天才だったと言えるかもね。

GCはこの言語のスーパーパワーだと思う。パフォーマンスにあまり気を使わずに素早くプロトタイプが作れるし、いつでも同じコードに戻ってmallocを使って書き直すこともできる。C#やJavaにはこれがないし、Cコードをコンパイルしてシームレスに連携することもできないけど、Dではそれが楽にできる。さらに深く掘り下げると、Dは他の高級言語よりも遥かにガーベジコレクタをコントロールできるから、必要なところでメモリのチャンクをすぐに解放して、GCのストップを最小限に抑えたり、なくしたりすることもできるんだ。

Dについての私の(多分不公平な)印象は、ちょっと舵取りがない感じ。あまりにも多くの人に合わせようとしてるから、パラダイムにコミットしてる言語と比べて目立たないんだよね。GCが欲しい?いいよ!GCがいらない?それならオフにできるけど、大半の機能が使えなくなるよ。借用チェッカーが欲しい?それもDはできるけど、Rustほど本気じゃない。もっと安全なC/メモリ安全が欲しい?SafeDモードがあるよ。多分、他にも忘れてることがあるけど。こういう異なる(しばしば互換性のない)使い方がDのエコシステムを分断して、重要な規模を得るのがさらに難しくなるのかな。

Zigについてのポイントに関して:特に学生の頃にDのBetterCモデルをたくさん使って遊んでたから、言語デザイナーとしてウォルターがZigの開発や人気の上昇についてどう思ってるのか気になるな。もちろん、言語の採用について「戦略的」に考えるのは、エンジニアや tinkerer の中ではマキャベリズムに聞こえるけど、どうしても気になっちゃうよね。

Zigは「隠れた挙動」を避けることにこだわりすぎて、デストラクタや演算子オーバーロードが禁止されちゃったんだよね。演算子オーバーロードは確かに厄介だけど、デストラクタはめっちゃ便利だよ。デストラクタに関して唯一の妥協点は「defer」機能を追加したことかな。 (「deferしないとエラーになる」機能ってあったっけ?)

GC/runtime 1. ランタイム: ランタイムは、プログラムのコードをコンパイルした結果ではないコードのことだよ(つまり、異なるプログラムで使われる)。これは、実行可能ファイルに静的または動的にリンクされる。80年代にCを学んだとき、教科書に「Cは単なる言語ではなく、豊かなランタイムだ」と書いてあったのを覚えてる。Rustも豊かなランタイムを持ってる。Rustはランタイムなしで書けるモードもあるけど、そうすると文字列すらほとんど使えないし、ほとんどのRustプログラムはランタイムを使ってる。Javaの一般的な使われ方の違いは、ランタイムがあることじゃなくて、ランタイムに含まれるJITコンパイラに依存していることだよ。JITには利点と欠点があるけど、「ランタイム」の一般的な特徴ではない。 2. GC: ガーベジコレクタは、オブジェクトが到達不能になった後にヒープオブジェクトのメモリを自動的に再利用するメカニズムだよ。2つの古典的なGC設計、参照カウントとトレーシングは60年代にさかのぼり、異なる方法で進化してきた。例えば、80年代と90年代には、コンパイラが非エスケープオブジェクトのライフタイムを推測して静的にfreeを挿入したり、言語がライフタイムを追跡して(「領域」、1994年)、コンパイラが言語に注釈された情報に基づいて静的にfreeを挿入したりするGC設計があった。一方、80年代にはアンドリュー・アップルが「移動トレーシングコレクタはスタック割り当てより速いことがある」と有名に示した。だから、異なるGCはオブジェクトの到達可能性に関する静的推論と動的情報の異なる組み合わせを使って、フットプリントやスループットなどの異なるものを最適化している。GCがあるかないかのトレードオフがあって、Rust(GCあり)とZig(GCなし)間にもトレードオフがあるけど、ほとんどのトレードオフは異なるGCアルゴリズム間にある。Java、Go、Rustはそれぞれ異なるGCを使っていて、トレードオフも違う。だから、今のように「ランタイム」や「GC」という用語をカジュアルに使うことの問題は、文献と違うからじゃなくて、実際のトレードオフを見逃していることなんだ。ランタイムを静的にリンクすることの利点と欠点、AOTとJITコンパイルの利点と欠点、参照カウント/「静的」GCアルゴリズムと移動トレーシングアルゴリズムの利点とコストについて話すことはできるけど、GCやランタイムがあるかないかについて一般的に話すのはあまり役に立たないよね。なぜなら、最も関連性のある特性を表現していないから。

DはC#やJavaと同じカテゴリだと思ってたけど、2つの重要な違いに気づいた。(C#/.NetよりJava/JVMの方がずっと経験があるから、全てが当てはまるわけじゃないけど。)1. ネイティブライブラリの呼び出しにかなりのオーバーヘッドがある。JavaからJNIを使ってネイティブライブラリをラップするのは、かなり複雑なコードやビルドシステムの設定が必要で、呼び出しのオーバーヘッドもある。だから、ほとんどのプロジェクトはJVM言語で書かれたライブラリしか使わないんだ。Pythonの世界のように統合が広がっているわけじゃない。Foreign Function and Memory (FFM) APIはこれをかなり簡単にしてくれるはずだけど、プロジェクトがネイティブライブラリをもっと頻繁に統合するかどうかは見てみないとわからない。俺の理解では、Goの外部関数呼び出しも高コストだよ。2. VMが必要ない。JavaとC#はVMが必要だけど、D(Goのように)はネイティブバイナリを生成する。だから、Dはネイティブライブラリの周りにグルーコードを書くときにすごくいい選択肢なんだ。Dは簡単にできて、呼び出しのオーバーヘッドも少ないし、データ型の表現が一貫しているからデータのマシュリングやアンマシュリングの必要もあまりない。Dは認知的オーバーヘッドが低くて、プロトタイピングのときに役立つガードレールが多いし、特にC++のテンプレートと比べてコンパイル・デバッグのループが速くて便利なんだ。

ここでDが定期的に投稿されてるのを見かけるけど、まるで死んだ馬を叩いてるみたいだね。希望がないのにおばあちゃんを延命治療してるのと同じだ。

Dコミュニティがどれだけ活発か、驚くかもしれないよ。確かに「競合する」言語(実際には競争じゃないけど)の中では目立って小さいけどね。最新のリリースは1月7日で、Dartの最新リリースよりも多くのアップデートが含まれてるよ。Dartは大企業がバックについてるのにね。1. https://dlang.org/changelog/2.112.0.html

ちょっと前にDを触ってみたけど、いい言語だと思った。今のプログラミング言語の状況を考えると、Dでプログラムを書く理由が難しいよね。機能が重複している言語がたくさんあるし、開発者をどれだけ早く増やす必要があるか、言語を学ぶ速度(文法だけじゃなくて)にもよるから、人気も重要だよね。俺はコンサルタントやってるから、クライアントのためにいつもこれを考慮してる。