D语言

D语言是一种程式语言，具备多范型，例如物件导向、指令式。由沃尔特·布莱特和安德烈·亚历山德雷斯库所开发，起源自C++，深受C++的影响，然而其不是C++的变种，而是重新设计来自C++的部分特性，并受到其它程式语言观念的影响，如Java、C♯以及Eiffel。2007年1月2日释出1.0稳定版本。2007年1月17日释出2.0版本。

Walter Bright本身是Symantec C++编译器的作者，另一名作者安德烈·亚历山德雷斯库是Facebook的研究科学家，他与一个团队用D语言重写一些Facebook的重要操作。

## 特性

D的设计来自实际的C++用法的经验教训，而不是从理论的角度。D沿用了很多C/C++观念，同时摒弃了一些概念，因此D并不完全相容C/C++代码。D实现了C++的功能，实现了契约式设计（design by contract）、单元测试、真正的模组性、自动化内存管理（垃圾回收）、头等数组（first class array）、关联数组、动态数组、数组切片、嵌套函数（巢状函式）、内部类别、闭包的限制形式、匿名函式、编译时期函式执行、惰性计算以及革新的模板语法。D保有C++的性能以进行低阶程式设计，并加入完整的内联组译器支援。C++的多重继承改以Java 单继承与界面混合的风格取代。D的声明、语句和表达式语法 (程式语言)几乎和C++一样。

内联组译器（inline assembler）象征了D和Java、C#等应用程序语言的不同。内联组译器让程式员输入机器特定的组合语言码，如同标准D代码—通常由系统程式员使用的技术，以存取处理器的低阶功能，直接以硬件下的界面执行程式，如操作系统以及驱动程式。

D内建支援文件注解，不过目前为止，只有Digital Mars实作版本有提供文件产生器。

### 程式设计范型

D支援五种主要的程式设计泛型—指令式、物件导向以及元程式设计、函数式和并发（演员模型）。

#### 指令式

指令式程式设计几乎和C一样。函式、资料、语句、宣告以及表达式的运作就如同C一般，且可直接存取C执行时期程式库。

#### 物件导向

在D里面的物件导向程式设计，是以单继承分层结构，配合所有类别衍伸自类别物件为基础。多重继承可使用界面（界面很像C++的抽象类别）。

#### 元程式设计

以模板组合、编译时期函式执行、多元组以及字串混合来支援元程式设计。

### 内存管理

内存通常以垃圾回收管理，不过当这些物件超出作用域时，可立即结束指定的物件。还是可以使用重载运算子new和delete，以及简单的直接呼叫C的malloc函数和free函数以进行显示的内存管理。垃圾回收可禁用个别的物件或事件，以健全整个程式，如果在内存管理上有更多的控制，则更为理想。当垃圾回收在程式中有所不足时，手册还提供许多如何实作不同的高度最佳化内存管理方案的范例。

### 与其它系统的相互作用

支援C的应用程序二进制界面（ABI），以及C的基本和衍伸型态，就能直接存取现有的C代码以及程式库。C的标准函式库也是D标准的一部分。除非你使用非常清楚的命名空间，它可以稍微散乱的存取，因为它散布遍及于D模组—不过纯粹的D标准函式库也通常够用，除非要与C代码接合。

并未完整支援C++的ABI，尽管D可以存取写给C ABI的C++代码，且可存取C++COM（元件物件模型）代码。D语法分析器了解外部（C++）呼叫约定，以连结C++物件，不过它只实作在D 2.0。

## D 2.0

D 2.0，D 新一代版本，D2.0与D1.0是不兼容的，类似Python2和Python3的区别。目前D2已经稳定下来。其中一部分特性包括支援强制常数正确性（const-correctness），以及有限的支援连结以 C++ 编写的代码。

## 实现

目前D直接编译成原生码以高效执行。

D语言1.x版本已稳定，不再功能变更或扩展，2.0版本是其正式版本，不完全相容旧版本的语言和编译器。官方编译器由Walter Bright定义语言本身。

- DMD编译器：Digital Mars D编译器，由Walter Bright编写的官方D编译器。编译器前端的授权许可为Artistic License和GNU GPL两者；前端的源代码连同编译器执行码一起发布。编译器的后端则是私有的。
- GDC：D 1.0编译器，以DMD编译器前端，以及GCC后端所组成。
- LDC：D 2.0编译器，以DMD编译器前端，以及LLVM后端所组成。LDC的官方版本已不支持D1.0，但其分支版本依然支持D1.0。

## 问题和争议

### 运算子重载

D运算子重载在一定程度上不如C++强大。简单的例子是opIndex，它不允许返回引用。这使像是obji = 5;的赋值不可能存在。D的解决方法是opIndexAssign运算子，它只用于这种特殊情况。此外，C++返回参考的方法允许返回型态的重载赋值运算子的用法。这在目前的D还不可能做到。D 2.0将会引入opIndexLvalue修正 - 类似运算子重载和opIndexAssign。

### 低功的结构

结构在D之中是一种朴素旧式资料的型态，不过也可像变数一样包含方法。这对有意轻量化的建构而言相当实用，如矩阵或向量，这些不需要完整的D类别功能（以及体积）。然而，D结构没有建构子和解构子。建构子可用静态opCall运算子部分取代，不过它没有适合的解构子等价物。此外，结构不允许继承，这会是有益的设计，如诡异循环模板模式（curiously recurring template pattern）的使用。

### 标准函式库中缺乏功能

D的标准函式库称作 Phobos，且时常被认为过分简单。tango专案编写另一个标准函式库试图修正这一部分，不过phobos和tango目前由于不同的物件类别实作（导致垃圾回收困难）而互不相容。存在两种事实上的标准函式库可能导致更大的问题，部分软件使用phobos，而其它软件使用tango。

### 缺乏明确的目标

D经常限于“修正并改进的C++”。这会导致过分强调功能，这起因于加入新功能只是因为他们认为有用。举个例子，关联阵列可简单的以标准函式库实现。

### 未完成对共享／动态函式库的支持

Unix的ELF共享函式库使用GDC编译器支持到某个程度。在Windows系统中，目前还不支援DLL。因此现阶段不可能编写插件。不像C++，经由C函式传送的D物件将不能运作，因为这将会与垃圾回收器产生冲突。

## 范例

### 范例1

这个范例程式会输出它自己的命令列参数。main函式是D程式的进入点，args是表示为字串阵列的命令列参数。在D语言里的字串是一个字元阵列，以char表示。新版本中定义string为char的别名，不过别名定义必须与旧版本相容。

```D
import std.stdio;       // 以使用writefln()
alias char[] string;    // 以相容舊的編譯器；新的編譯器中已隱含定義
int main(string[] args)
{
    foreach(i, a; args)
        writefln("args[%d] = '%s'", i, a);
    return 0;
}
```

foreach语法可迭代所有的集合，在本例中，它从args阵列生成索引（i）和值（a）的序列。索引i和值a的型态会从args阵列的型态推断。

### 范例2

本例使用关联阵列建立更复杂的资料结构。

```D
import std.stdio;       // 以使用writefln()
alias char[] string;    // 以相容舊的編譯器；新的編譯器中已隱含定義

int main(string[] args)
{
    // 宣告以字串鍵和字串陣列作為資料的關聯陣列
    string[] [string] container;

    // 將人們加入到容器中，並讓他們攜帶一些項目
    container["Anya"] ~= "scarf";
    container["Dimitri"] ~= "tickets";
    container["Anya"] ~= "puppy";

    // 迭代容器中所有的人
    //Iterate over all the persons in the container
    foreach (string person, string[] items; container)
        display_item_count(person, items);
    return 0;//完成
}

void display_item_count(string person, string[] items)
{
    writefln(person, " is carrying ", items.length, " items.");
}
```

### 范例3

本例繁多的注解显示出D语言与C++ 的不同之处，以及仍然保留的方面。

```D
#!/usr/bin/dmd -run
/* 支援sh風格的script語法！*/
/* D語言的Hello World
 * 進行編譯：
 *   dmd hello.d
 * 或進行最佳化：
 *   dmd -O -inline -release hello.d
 * 或產生文件：
 *   dmd hello.d -D
 */

import std.stdio;       // 參照常用的I/O例行工作。
alias char[] string;    // 以相容舊的編譯器；新的編譯器中已隱含定義

int main(string[] args)
{
    // 'writefln' (寫入-格式化-行，Write-Formatted-Line)即型態安全的「printf」
    writefln("Hello World, "             // 自動連結的字串文字
             "Reloaded");

    // 字串即字元的動態陣列「char[]」，別名為「string」
    // 自動的型態推斷，以及內建的foreach
    foreach(argc, argv; args)
    {
        auto cl = new CmdLin(argc, argv);                       // 支援OOP
	writefln(cl.argnum, cl.suffix, " arg: %s", cl.argv);    // 使用者定義的類別屬性。

	delete cl; 	              // 垃圾回收或顯示的記憶體管理——由你自己選擇
    }

    // 巢狀結構、類別和函式
    struct specs
    {
        // 所有的變數會在執行時期自動初始化為0
        int count, allocated;
 	// 不過你可選擇避開陣列的初始化
        int[10000] bigarray = void;
    }

    specs argspecs(string[] args)
    // 可選用的（內建）函式契約。
    in
    {
        assert(args.length > 0);                   // 內建assert
    }
    out(result)
    {
        assert(result.count == CmdLin.total);
        assert(result.allocated > 0);
    }
    body
    {
        specs* s = new specs;
        // 不需要「->」
        s.count = args.length;  // 「length」屬性是元素的數量。
        s.allocated = typeof(args).sizeof; // 原生型態內建的屬性
 	foreach(arg; args)
 	    s.allocated += arg.length * typeof(arg[0]).sizeof;
 	return *s;
    }

    // 內建字串和普通的字串操作，例如「~」是連結。
    string argcmsg = "argc = %d";
    string allocmsg = "allocated = %d";
    writefln(argcmsg ~ ", " ~ allocmsg,
	    argspecs(args).count,argspecs(args).allocated);
    return 0;
}
 
/**
 * 儲存單獨命令列參數
 */
class CmdLin
{
    private
    {
        int _argc;
        string _argv;
        static uint _totalc;
    }
 
    public:
        /**
         * 物件的建構子。
         * 參數：
         *   argc = 參數的序列計數。
         *   argv = 參數內文。
         */
        this(int argc, string argv)
        {
            _argc = argc + 1;
            _argv = argv;
            _totalc++;
        }

        ~this() // 物件的解構子
        {
            // 本例中不做任何事。
        }

        int argnum() // 屬性，可返回參數數目
        {
            return _argc;
        }

        string argv() // 屬性，可返回參數內文
        {
            return _argv;
        }

        wstring suffix() // 屬性，可返回序數後綴
        {
            wstring suffix; // 內建Unicode字串（UTF-8，UTF-16，UTF-32）
            switch(_argc)
            {
                case 1:
                    suffix = "st";
                    break;
                case 2:
                    suffix = "nd";
                    break;
                case 3:
                    suffix = "rd";
                    break;
                default:  // 'default' is mandatory with "-w" compile switch.
                    suffix = "th";
            }
            return suffix;
        }

        /**
          * 靜態屬性，如同在C++ 或Java中。
          * 適用於類別物件，而不是實體。
          * 返回：己加入的命令列參數總數。
          */
        static typeof(_totalc) total()
        {
            return _totalc;
        }

        // 類別不變量，任何方法在執行之後，這些必須為真。
        invariant ()
        {
            assert(_argc > 0);
            assert(_totalc >= _argc);
        }
}
```

### 范例4

本例显示出一部分D语言强大的编译时期特性。

```D
/*
 * D語言裡的模板比C++ 的要更加強大。
 * 在此可以看到使用static if（D的編譯時期條件建構）簡單的建構出階乘模板。
 */
template Factorial(ulong n)
{
    static if( n <= 1 )
        const Factorial = 1;
    else
        const Factorial = n * Factorial!(n-1);
}

/*
 * 這裡有一個正規的函式，可完成同樣的計算。
 * 注意它們有多麼的相似。
 */
ulong factorial(ulong n)
{
    if( n <= 1 )
        return 1;
    else
        return n * factorial(n-1);
}

/*
 * 終於，我們可以計算我們的階乘。注意，我們不需要去
 * 明確的指定我們的常數的型態：編譯器有足夠的智能為
 * 我們填充空白，因為它早已知道賦值中右手邊的型態。
 */
const fact_7 = Factorial!(7);

/*
 * 這是編譯時期函式評估的範例：普通函式可用於常數。
 * 編譯時期表達式，假若它們滿足一定的條件。
 */
const fact_9 = factorial(9);

/*在此我們可以看到多麼強大的D我們使用 
 * std.metastrings.Format模板完成型態安全的printf 
 * 資料格式化，並使用message pragma顯示計算結果。
 */
import std.metastrings;
pragma(msg, Format!("7! = %s", fact_7));
pragma(msg, Format!("9! = %s", fact_9));

/*
 * 完成任務後，我們可以強制停止編譯。這樣的程式需是
 * 從未實際編譯成可執行檔！
 */
static assert(false, "My work here is done.");
```

## 外部链接

- Digital Mars: D程式语言（官方网站）
- Computers/Programming/Languages/D/
- DSource，D语言的开放源代码社群。
- Dprogramming.com，视窗化程式库DFL的首页。
- Wiki4D，“D语言的维基页”
- gdc，GCC的D语言前端
- 电脑语言评测游戏
- D文件的维基页
- D语言特性列表
- Walter Bright介绍D语言的影片
- Ddbg - Win32 D除错器
- DWin - D语言库
- DLogo - D语言按钮，广告栏
- SciTE4D - D语言编辑器* D语言中国社区， D语言入门，D语言GUI介绍等
- D语言中文讨论区
- D Programming Language简介
- D语言教学

## 基本资料

- 编程范型：多范型：函数式、指令式、面向对象
- 类型系统：静态强类型
- 发行日期：2001年12月8日
- 设计者：Walter Bright，Andrei Alexandrescu
- 软件版本周期：2.112.0
- 软件版本周期：2026年1月7日，2026年1月7日
- 软件实现： DMD、 GDC、 LDC
- 受影响于：C、C++、C#、Java、Eiffel