D語言

D語言是一種程式語言，具備多範型，例如物件導向、指令式。由沃爾特·布萊特和安德烈·亞歷山德雷斯庫所開發，起源自C++，深受C++的影響，然而其不是C++的變種，而是重新設計來自C++的部分特性，並受到其它程式語言觀唸的影響，如Java、C#以及Eiffel。2007年1月2日釋出1.0穩定版本。2007年1月17日釋出2.0版本。Walter Bright本身是Symantec C++編譯器的作者，另一名作者Andrei Alexandrescu是Facebook的研究科學家，他與一個團隊用D語言重寫一些Facebook的重要操作。特性.D的設計來自實際的C++用法的經驗教訓，而不是從理論的角度。D沿用了很多C/C++觀念，同時摒棄了一些概念，因此D並不完全相容C/C++程式碼。D實現了C++的功能，實現了契約式設計、內部類別、閉包的限制形式、匿名函式、編譯時期函式執行、惰性計算以及革新的模板語法。D保有C++的效能以進行低階程式設計，並加入完整的內聯組譯器支援。C++的多重繼承改以Java 單繼承與介面混合的風格取代。D的支援到某個程度。在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的型態會從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 containerforeach (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 -Dimport std.stdio; // 參照常用的I/O例行工作。alias char[] string; // 以相容舊的編譯器；新的編譯器中已隱含定義int main(string[] args)// 'writefln' (寫入-格式化-行，Write-Formatted-Line)即型態安全的「printf」writefln("Hello World, " // 自動連結的字串文字"Reloaded");// 字串即字元的動態陣列「char[]」，別名為「string」// 自動的型態推斷，以及內建的foreachforeach(argc, argv; args)auto cl = new CmdLin(argc, argv); // 支援OOPwritefln(cl.argnum, cl.suffix, " arg: %s", cl.argv); // 使用者定義的類別屬性。delete cl; // 垃圾回收或顯示的記憶體管理——由你自己選擇// 巢狀結構、類別和函式struct specs// 所有的變數會在執行時期自動初始化為0int count, allocated;// 不過你可選擇避開陣列的初始化int[10000] bigarray = void;specs argspecs(string[] args)// 可選用的函式契約。inassert(args.length &gt; 0); // 內建assertout(result)assert(result.count == CmdLin.total);assert(result.allocated &gt; 0);bodyspecs* 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 CmdLinprivateint _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字串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簡單的建構出階乘模板。template Factorial(ulong n)static if( n &lt;= 1 )const Factorial = 1;elseconst Factorial = n * Factorial!(n-1);* 這裡有一個正規的函式，可完成同樣的計算。* 注意它們有多麼的相似。ulong factorial(ulong n)if( n &lt;= 1 )return 1;elsereturn 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.");