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的-{zh-tw:宣告;zh-cn:声明;}-、语句和表达式几乎和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定义语言本身。
问题和争议.
运算子重载.
D运算子重载在一定程度上不如C++强大。简单的例子是opIndex，它不允许返回引用。这使像是obj[i] = 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++」。这会导致过分强调功能，这起因于加入新功能只是因为他们认为有用。举个例子，
未完成对共享／动态函式库的-{zh:支援; zh-hans:支持; zh-tw:支援;}-.
Unix的ELF共享函式库使用GDC编译器-{zh:支援; zh-hans:支持; zh-tw:支援;}-到某个程度。在Windows系统中，目前还不支援DLL。因此现阶段不可能编写插件。不像C++，经由C函式传送的D物件将不能运作，因为这将会与垃圾回收器产生冲突。
范例.
范例1.
这个范例程式会输出它自己的命令列参数。main函式是D程式的进入点，args是表示为字串阵列的命令列参数。在D语言里的字串是一个字元阵列，以char[]表示。新版本中定义string为char[]的别名，不过别名定义必须与旧版本相容。
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.
本例使用关联阵列建立更复杂的资料结构。
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++ 的不同之处，以及仍然保留的方面。
/* 支援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 &gt; 0); // 内建assert
 out(result)
 assert(result.count == CmdLin.total);
 assert(result.allocated &gt; 0);
 body
 specs* s = new specs;
 // 不需要「-&gt;」
 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 &gt; 0);
 assert(_totalc &gt;= _argc);
范例4.
本例显示出一部分D语言强大的编译时期特性。
/*
 * D语言里的模板比C++ 的要更加强大。
 * 在此可以看到使用static if（D的编译时期条件建构）简单的建构出阶乘模板。
template Factorial(ulong n)
 static if( n &lt;= 1 )
 const Factorial = 1;
 else
 const Factorial = n * Factorial!(n-1);
 * 这里有一个正规的函式，可完成同样的计算。
 * 注意它们有多么的相似。
ulong factorial(ulong n)
 if( n &lt;= 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.");