Advertisement
Guest User

Untitled

a guest
Sep 8th, 2012
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.24 KB | None | 0 0
  1. 他の言語をある程度知っている人はこれを読めばD言語の基礎をマスターでき,D言語の氷山の一角くらいは知ることができると思います.対象バージョンはdmd 2.059です.
  2.  
  3. # 1. 基礎
  4.  
  5. ## ソースファイル
  6. ASCIIかUTFしか受け付けません.それ以外の文字コードで書くとコンパイルエラーになります.
  7.  
  8. ## main
  9.  
  10. D言語のmainはCとは違い以下のようなシグネチャです.
  11.  
  12. ```d
  13. void main();
  14. void main(string[] args);
  15. ```
  16.  
  17. リターンコードについては処理系がよしなにやってくれます.
  18.  
  19. ## 表示 (write(ln), writef(ln))
  20.  
  21. 標準ライブラリにあるstd.stdioを使います.
  22.  
  23. ```d
  24. import std.stdio;
  25. ...
  26. write(1); // 改行無し
  27. writeln(1); // 改行有り
  28. writef("%02d", 1); // フォーマット指定
  29. ```
  30.  
  31. ## 変数の宣言
  32.  
  33. D言語では"型 変数名"というように宣言します.
  34.  
  35. ```d
  36. int a; // デフォルト値で初期化される.intは0
  37. int a = void; // 初期化されず,Cなどと同じくゴミが入っている
  38. ```
  39.  
  40. また,初期化子から型を推論するためのautoという予約語があります.
  41.  
  42. ```d
  43. auto a = "auto"; // aはimmutable(char)[]型
  44. ```
  45.  
  46. 他の修飾子がある場合も型推論が効きます.
  47.  
  48. ```d
  49. const a = "const";
  50. ```
  51.  
  52. ## データ型
  53.  
  54. 値型と参照型があります.以下は値型の一例です.
  55.  
  56. ```d
  57. // ブール値
  58. bool flag;
  59.  
  60. // 符号なし8bitのUTF-8文字(マルチバイトじゃないので注意)
  61. char c;
  62.  
  63. // 数値はCとは違いサイズ固定です.
  64. byte num1; // 8bit
  65. short num2; // 16bit
  66. int num3; // 32bit
  67. double num4; // 64bit
  68.  
  69. // 静的配列
  70. int[5] arr;
  71.  
  72. // 構造体
  73. Random random;
  74. ```
  75.  
  76. 参照型は複合的なデータ構造などが当てはまります.
  77.  
  78. ```d
  79. // 動的配列 (スライス)
  80. int[] arr;
  81.  
  82. // オブジェクト
  83. Object obj;
  84.  
  85. // デリゲート
  86. void delegate(void) action;
  87. ```
  88.  
  89. 参照型と言っても実はポインタの値渡しみたいなものです.
  90.  
  91. ## コメント
  92.  
  93. 4種類あります.
  94.  
  95. ```d
  96. // 一行コメント
  97.  
  98. /*
  99. 複数行コメント
  100. */
  101.  
  102. /**
  103. DDocコメント
  104. */
  105.  
  106. /+ /+
  107. ネスト可能複数行コメント
  108. +/ +/
  109. ```
  110.  
  111. ## プログラムの実行
  112.  
  113. コンパイル.
  114.  
  115. ```sh
  116. $ dmd foo.d
  117. $ ./foo
  118. ```
  119.  
  120. runオプション使うと実行ファイルなどを生成せずに実行できます.
  121.  
  122. ```sh
  123. $ dmd -run foo.d
  124. ```
  125.  
  126. -runの依存関係解決などを強化したrdmdも同梱されています.また,--evalで簡単にコードを試せたりもします.
  127.  
  128. ```sh
  129. $ rdmd foo.d
  130. $ rdmd --eval="writeln(10);"
  131. ```
  132.  
  133. # 2. 数値
  134.  
  135. 整数.uがつくと符号なしになります.
  136.  
  137. ```d
  138. long num = -1; // 符号つき
  139. ulong num = 100_000_000; // 符号なし
  140. ```
  141.  
  142. 浮動小数点数.
  143.  
  144. ```d
  145. double num = 1.234;
  146. real num = 5.678; // ハードウェア依存(x86 CPUなら80bit)
  147. ```
  148.  
  149. 複素数も使えたりします.
  150.  
  151. ```d
  152. creal num = 1 + 2i;
  153. num += 3i;
  154. writeln(num.re, num.im); // reが実部(1),imが虚部(5)
  155. ```
  156.  
  157. この組み込み複素数はstd.complexで置き換えられる予定です(まだ期日は決まってません).
  158.  
  159. ## 四則演算
  160.  
  161. ```d
  162. // numはintとする
  163. num = 1 + 1;
  164. num = 1 - 1;
  165. num = 1 * 2;
  166. num = 5 / 2; // 2
  167. num = 5 % 2; // 1
  168. ```
  169.  
  170. 演算子のどちらかが浮動小数点数の場合,結果も浮動小数点数になります.
  171.  
  172. ```d
  173. // numはdoubleとする
  174. num = 5.0 / 2; // 2.5(numがintなどの整数型だとコンパイルエラー)
  175. ```
  176.  
  177. ## インクリメントとデクリメント
  178.  
  179. 勿論あります.
  180.  
  181. ```d
  182. i++;
  183. --i;
  184. ```
  185.  
  186. # 3. 文字列
  187.  
  188. 文字列はダブルクォートで囲みます.ダブルクォートの中では\t(タブ)や\n(改行)などの特殊文字を利用することができます.
  189.  
  190. ```d
  191. string str1 = "abc";
  192. string str2 = "a\tbc\n";
  193. ```
  194.  
  195. D言語での文字列は4で述べる配列の一種に過ぎません(stringはimmutable(char)[]のaliasです).またポストフィックスをつけることでリテラルの型を指定できます.
  196.  
  197. ```d
  198. string str3 = "hello"c // 各文字はchar型
  199. wstring str4 = "hello"w // 各文字はwchar型
  200. dstring str5 = "hello"d // 各文字はdchar型
  201. ```
  202.  
  203. ## 文字列操作
  204.  
  205. ```d
  206. // 結合
  207. auto str = "aaa" ~ "bbb";
  208.  
  209. // 長さ(バイト)
  210. auto length = "abcdef".length;
  211.  
  212. // 切り出し
  213. auto substr = "abcd"[0..2]; // "ab"
  214.  
  215. /* これ以降のものはstd.stringが必要です */
  216.  
  217. // 分割
  218. auto record = "aaa,bbb,ccc".split(","); // ["aaa", "bbb", "ccc"]
  219.  
  220. // 検索
  221. auto idx = "abcd".indexOf("bc"); // 見つかった場合はその位置,見つからなかった場合は-1
  222. ```
  223.  
  224. # 4. 配列
  225.  
  226. 配列は「[]」を使います.静的配列と動的配列がありますが,よく使われる動的配列について書きます(動的配列は実はスライスだったりします.詳しくは[この記事](http://dlang.org/d-array-article.html)を参照).
  227.  
  228. ```d
  229. int[] arr = [100, 200, 300];
  230. ```
  231.  
  232. 宣言ではCとは違い前置形式となります.
  233.  
  234. ## 要素の参照と代入
  235.  
  236. ```d
  237. // 参照
  238. a = arr[0];
  239. b = arr[1];
  240. c = arr[5]; // Error! 要素数より多いと例外が投げられる
  241.  
  242. // 代入
  243. arr[0] = 1;
  244. arr[1] = 2;
  245. arr[5] = 5; // 参照と同じく
  246. ```
  247.  
  248. ## 要素の個数
  249.  
  250. ```d
  251. len = arr.length;
  252.  
  253. // 要素を増やす(増えた分はデフォルト値で埋められる)
  254. arr.length += 10;
  255. ```
  256.  
  257. ## 配列の操作
  258.  
  259. std.arrayを使うとD言語での標準的なインターフェイス(Range)が利用できます.
  260.  
  261. ```d
  262. import std.array;
  263.  
  264. auto arr = [1, 2, 3];
  265.  
  266. // 先頭を取得
  267. auto a = arr.front; // aは1
  268.  
  269. // 先頭を削除
  270. arr.popFront(); // arrは[2, 3]
  271.  
  272. // 先頭に追加(push系がないのでinsertで)
  273. arr.insert(0, 5); // arrは[5, 2, 3]
  274.  
  275. // 末尾を取得
  276. auto b = arr.back; // bは3
  277.  
  278. // 末尾を削除
  279. arr.popBack(); // arrは[5, 2]
  280.  
  281. // 末尾に追加
  282. arr ~= 9; // arrは[5, 2, 9]
  283. ```
  284.  
  285. popFrontやpopBackで値が返らないのは例外安全のためです.
  286.  
  287. ## ベクトル演算
  288.  
  289. いちいちループとか使う必要ありません.[]を使うことでベクトル演算できます.
  290.  
  291. ```d
  292. auto a = [1, 2, 3];
  293. a[] += 10; // [11, 12, 13]
  294. ```
  295.  
  296. # 5. 連想配列
  297.  
  298. 連想配列も「[]」を使います.キーと値を:で区切ります.
  299.  
  300. ```d
  301. int[string] hash = ["a" : 1, "b" : 2];
  302. ```
  303.  
  304. ## 要素の参照と代入
  305.  
  306. ```d
  307. // 参照
  308. hash["a"] // 1
  309. hash["b"] // 2
  310. hash["z"] // 配列と同じく例外が投げられる
  311.  
  312. // 代入
  313. hash["c"] = 5
  314. hash["d"] = 7
  315. ```
  316.  
  317. ## 連想配列の操作
  318.  
  319. ```d
  320. // キーの取得
  321. hash.keys; // ["a", "b", "c", "d"]
  322.  
  323. // 値の取得
  324. hash.values; // [1, 2, 5, 7]
  325.  
  326. // キーの存在確認
  327. auto val = "a" in hash; // valには1へのポインタ,なければnull
  328.  
  329. // ハッシュのペアの削除
  330. hash.remove("a");
  331. ```
  332.  
  333. # 6. 制御文
  334.  
  335. ## if文
  336.  
  337. ```d
  338. if (cond) {
  339. // do something
  340. }
  341. ```
  342.  
  343. ## if ~ else文
  344.  
  345. ```d
  346. if (cond) {
  347. // do something
  348. } else {
  349. // do something
  350. }
  351. ```
  352.  
  353. ## if ~ else if 文
  354.  
  355. ```d
  356. if (cond) {
  357. // do something
  358. } else if (cond) {
  359. // do something
  360. }
  361. ```
  362.  
  363. ## switch文
  364.  
  365. Cとは違い,文字列が使えたりcaseを並べて書くことが出来ます.
  366.  
  367. ```d
  368. switch (command) {
  369. case "foo", "bar":
  370. // do something
  371. break;
  372. case "baz":
  373. // do something
  374. break;
  375. default:
  376. }
  377. ```
  378.  
  379. ## while文
  380.  
  381. ```d
  382. uint i;
  383. while (i < 5) {
  384. // do something
  385. ++i;
  386. }
  387. ```
  388.  
  389. ## for文
  390.  
  391. ```d
  392. for (uint i; i < 5; i++) {
  393. // do something
  394. }
  395. ```
  396.  
  397. ## foreach文
  398.  
  399. 配列や,opApply/Rangeインターフェイスを実装しているオブジェクトを処理出来ます.
  400.  
  401. ```d
  402. foreach (elem; arr) {
  403. // do something
  404. }
  405. ```
  406.  
  407. 要素を弄りたかったらrefをつけます.
  408.  
  409. ```d
  410. foreach (ref elem; arr) {
  411. // do something
  412. }
  413. ```
  414.  
  415. # 7. 関数/デリゲート
  416.  
  417. 関数はCと同じようなものですが色々と指定できます.xはconstな値として入力を表し,refは参照として操作することを表します.lazyは遅延評価(zが関数内で使われるまで評価を遅延させる)を行います.
  418.  
  419. ```d
  420. nothrow void foo(in int x, ref int y, lazy int z = 0)
  421. {
  422. // do something
  423. }
  424. ```
  425.  
  426. デリゲートはネストされた関数などが該当します.これはクロージャの働きもします.
  427.  
  428. ```d
  429. uint delegate() createCounter()
  430. {
  431. uint count;
  432. return { return ++count; }; // {}はdelegateリテラル(引数がないので()は省略)
  433. }
  434.  
  435. auto counter = createCounter();
  436. writeln(counter()); // 1
  437. ```
  438.  
  439. 2.059から以下のようなラムダシンタックスがあります.
  440.  
  441. ```d
  442. void f(uint delegate(uint) d)
  443. {
  444. writeln(d(10));
  445. }
  446.  
  447. void main()
  448. {
  449. f((x) { return x + 2; });
  450. f(x => x + 2); // ラムダシンタックス(上のと等価)
  451. }
  452. ```
  453.  
  454. ## CTFE(Compile Time Function Excecute)
  455.  
  456. D言語ではコンパイル時に色々処理をすることが出来ます.クラスの生成も出来ますし,例外も投げれますし,もちろん数値計算や配列も操作出来ます.そのため,コンパイル時に定数を渡せば,それなりに色々な関数が動作します.
  457. たとえば,以下のような乱数生成も普通にコンパイル時に動きます.
  458.  
  459. ```d
  460. ulong gen()
  461. {
  462. Random r;
  463. popFrontN(r, 1000);
  464. return r.front;
  465. }
  466. ```
  467.  
  468. # 8. ファイル入出力
  469.  
  470. std.stdioにあるFileを使います.以下はコピーの例です.
  471.  
  472. ```d
  473. auto fin = File("orig.txt"); // デフォルトは読み込み
  474. auto fout = File("copy.txt", "w"); // 書き込みモードでオープン
  475.  
  476. foreach (line; fin.byLine)
  477. fout.write(line);
  478.  
  479. // Fileは参照カウントで管理されているので明示的なcloseは不要
  480. ```
  481.  
  482. # 知っておいた方がよい文法
  483.  
  484. ## D言語の真偽値
  485.  
  486. null,false,数値型の0,まだ割り当てられていない動的配列,は偽となります.最後の配列の挙動はどうにも怪しいため,配列関係はemptyを使って評価することをオススメします.
  487.  
  488. ## クラス
  489.  
  490. Javaと同等の機能を提供しています(単一継承です).
  491.  
  492. ```d
  493. class Person
  494. {
  495. private: // 以降はprivate
  496. string name_;
  497.  
  498. public: // 以降はpublic
  499. @property
  500. {
  501. // @properyをつけるとname()ではなくnameで呼び出せるようになる
  502. // p.name
  503. string name() const { return name_; }
  504. // p.name = newName
  505. void name(string name) { name_ = name; }
  506. }
  507.  
  508. this(string name) // コンストラクタはthis
  509. {
  510. name_ = name;
  511. }
  512.  
  513. ...
  514. } // Cなどと違い;はいらない
  515. ```
  516.  
  517. その他にもinterface,PODとして扱えるstructやunion,演算子オーバーロードなどもあります.また,D言語はGCを使ってメモリ管理しているため,newした後deleteする必要はありません(自らmallocなどした場合は勿論freeは必要です).
  518.  
  519. ## テンプレート
  520.  
  521. C++よりかはすっきり書けるようになってます.以下は階乗を計算するテンプレートです.
  522.  
  523. ```d
  524. template factorial(int n)
  525. {
  526. static if (n == 1)
  527. enum factorial = 1;
  528. else
  529. enum factorial = n * factorial!(n - 1);
  530. }
  531.  
  532. /* C++などとは違い<>を使わず!()を使う */
  533. factorial!(5) // 120
  534. ```
  535.  
  536. このようにD言語ではコンパイル時用のstatic ifがあったりします.
  537.  
  538. 勿論クラスや関数(UFCSの項参照)でも使えます.
  539.  
  540. ```d
  541. class Hoge(T)
  542. {
  543. T value;
  544. }
  545. ```
  546.  
  547. ### テンプレートミックスイン
  548.  
  549. 単一継承のD言語では,クラス間で実装を共有する時はテンプレートを使います.
  550.  
  551. ```d
  552. template HogeImpl()
  553. {
  554. uint hoge_;
  555. uint hogeTwice() { return hoge_ * hoge_; }
  556. }
  557.  
  558. class A
  559. {
  560. mixin HogeImpl; // Aで定義したかのように使える
  561. }
  562.  
  563. class B
  564. {
  565. mixin HogeImpl; // 同様
  566. }
  567. ```
  568.  
  569. ## UFCS (Uniform Function Call Syntax)
  570.  
  571. 第一引数をオブジェクトのように扱えるシンタックスシュガーです.2.058までは配列のみでしたが,2.059からintとかでも使えます.
  572.  
  573. ```d
  574. void foo(T)(T obj) {}
  575.  
  576. // 本来はfoo([1, 2, 3])とか
  577. [1, 2, 3].foo();
  578. 5.foo();
  579. 2.5f.foo();
  580. ```
  581.  
  582. std.arrayやstd.stringを使った関数がvar.methodのように呼べたのはこのためです.
  583.  
  584. ## 例外処理
  585.  
  586. Mutex(変数m)を例に.まずはよく知られているtry - catch - finally.
  587.  
  588. ```d
  589. lock(m);
  590. try {
  591. // do something
  592. } finally {
  593. unlock(m);
  594. }
  595. ```
  596.  
  597. スコープガード文を使った方法もあります.解放処理がとても近くなり,コードが見やすくなります.
  598.  
  599. ```d
  600. lock(m);
  601. scope(exit) unlock(m); // どんな理由であれ,スコープを出る時に呼ばれる
  602. // do something
  603. ```
  604.  
  605. RAIIのような方法も可能です.scopeで宣言された変数はスコープを抜ける時に破棄され,デストラクタを呼び出します.
  606.  
  607. ```d
  608. class Lock
  609. {
  610. Mutex m_;
  611.  
  612. this(Mutex m) { m_ = m; lock(m_); }
  613.  
  614. ~this() { unlock(m_); } // デストラクタは~this
  615. }
  616.  
  617. scope myLock = new Lock(m);
  618. // do something
  619. ```
  620.  
  621. ## Range
  622.  
  623. D言語の標準ライブラリは今このコンセプトを中心に開発されています.核となるstd.rangeに満たすべきインターフェイスが定義されています.以下はstd.rangeベースのアルゴリズムの例です.
  624.  
  625. ```d
  626. import std.algorithm;
  627.  
  628. auto arr = [1, 2, 3, 4, 5];
  629.  
  630. // 条件に合うものだけを選ぶ
  631. filter!("a % 2 == 0")(arr); // [2, 4]
  632. // '"a % 2 == 0"'の代わりに'a => a % 2 == 0'でもOK.delegateと文字列両方受け付ける
  633. filter!(a => a % 2 == 0)(arr); // [2, 4]
  634.  
  635. // 条件に合うものを除く
  636. remove!("a % 2 == 0")(arr); // [1, 3, 5]
  637.  
  638. // 加工結果をRangeで返す
  639. map!("a * a")(arr); // [1, 4, 9, 16, 25]
  640.  
  641. // 降順にソートする
  642. sort!("a > b")(arr); // [5, 4, 3, 2, 1]
  643. ```
  644.  
  645. 基本的に,これらのアルゴリズムが返すのはarrの型ではなく,それぞれの計算を隠蔽したRangeオブジェクトです.これによって,Rangeは基本的には計算を遅延し,それぞれのRangeをつなげても,なるべく中間のオブジェクトを作らないようにしています.
  646. 配列として結果を返して欲しい時はstd.array.arrayを使います
  647.  
  648. ```d
  649. import std.array;
  650.  
  651. array(map!("a * a")(arr));
  652. ```
  653.  
  654. 8で上げたFileなども含め,他のモジュールもRangeベースとなっています.
  655.  
  656. ## 単体テスト
  657.  
  658. unittestで囲った所にテストをかけます.クラス内でも構わないので,より近くに書くのがD言語の作法です.
  659.  
  660. ```d
  661. unittest
  662. {
  663. bool foo() { /* do something */ return flag; }
  664. assert(foo());
  665. }
  666. ```
  667.  
  668. これはコンパイル時にunittestオプションを渡すことで実行されるようになります.
  669.  
  670. # 終わりに
  671.  
  672. template/契約/TLS/型システムあたり含め,全然魅力を書けてない気もしますが基本ということでまぁこんな感じで許して下さい.他に詳しく知りたい方はTwitterで #d_lang をつけてつぶやくか,以下のサイトを参考にしてみてください.この記事を必要であれば随時アップデートしていきます.
  673.  
  674. - [公式サイト](http://www.digitalmars.com/d/2.0/index.html)
  675. - [公式サイトの日本語訳](http://www.kmonos.net/alang/d/)
  676. - [dusers: 日本でのポータルサイト](http://dusers.dip.jp/)
  677. - [わかったつもりになるD言語](http://www.kmonos.net/alang/wnd/)(Phobosなどに古い記述がありますが,templateなどの内容が参考になります)
  678.  
  679. ## 本
  680. - [The D Programming Language](http://www.amazon.co.jp/D-Programming-Language-Andrei-Alexandrescu/dp/0321635361)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement