削除された内容 追加された内容
Angol Mois (トーク | 投稿記録)
Angol Mois (トーク | 投稿記録)
編集の要約なし
91 行
:4行目の <code>{</code> に対応する閉じカッコです。
 
== D言語の文法基礎 ==
この節では、D言語のプログラムがどういう見た目をしているか、その全体像をまとめたものが書かれています。それぞれについてもう少し詳しく書かれたものはもっと下の節にありますので、そちらを参照してください。
 
157 行
また、コメントをドキュメント化することもできます。<code>///</code> <code>/** */</code> と書かれたコメントはドキュメント化の対象となります。詳しくは[[D言語/ddoc]]をご覧ください。
 
=== 変数宣言 ===
変数とは、値を格納するものです。
 
180 行
変数に値を「代入する」という操作によって、変数が格納する値が変化します。代入という操作は、等号 "=" を用いて表します。これは数学の等号とは意味が異なるので、注意が必要です。
 
=== 関数宣言 ===
プログラミングをする際に、決まった同じ処理をしたくなる場合があるはずです。その際にコードを再利用することができるよう、関数というものが備わっています。これも数学の意味での関数とは違って、副作用を持つことができるので、「手続き」としばしば呼ばれます。
 
251 行
と、返値の型にも <code>ref</code> をつければ解決します。
 
==== UFCS ====
関数呼び出しがいくつも重なると、読みにくくなることがあります。例えば、
 
<code>writeln(twice(add(add(n, 10), 20)));</code>
=== 文 ===
 
というコードは非常に読みにくいです。そこで活躍のするのが統一関数呼び出し構文(UFCS)です。これはおおざっぱに言ってしまえば、<code>a.f(b, c, ...)</code> を <code>f(a, b, c, ...)</code> と(コンパイラが内部的に)書き換えることです。[[D言語/オブジェクト指向|オブジェクト指向]]がわかる方は、メソッドの呼び出しのように書くことができるものだと理解できるでしょう。これを使うと先程のコードは以下のようになります。
 
<code>n.add(10).add(20).twice().writeln();</code>
 
これでだいぶスッキリしましたが、今度は <code>twice writeln</code> のあとにつくカッコすらも煩わしく感じてしまいます。これを省略するには、関数定義の際に <code>@property</code> 属性をつければよいです。つまり、
<syntaxhighlight lang="D">
auto twice(int n) @property { ... }
</syntaxhighlight>
と定義すれば良いです。なお、<code>writeln</code> についても同様に省略可能です。
 
=== 制御文 ===
プログラムを書く際には条件分岐やループといった機能が活躍します。[[w:フィボナッチ数列|フィボナッチ数列]]を計算する関数を定義してみましょう。
 
;コード例 (悪い例)
<syntaxhighlight lang="D">
import std.stdio;
 
long fibonacci(long n) {
if (n < 0) {
return 0;
}
else if (n == 1) {
return 1;
}
else {
return fibonacci(n-1) + fibonacci(n-2);
}
}
 
void main() {
writeln(fibonacci(10));
}
</syntaxhighlight>
 
;実行結果
55
 
早速出てきました。if-else 文です。
<pre>
if (条件式) {
条件式が真だったときに実行される文
}
else {
条件式が偽だったときに実行される文
}
</pre>
上のコードでは、引数が 0 以下であるときは 0 を返し、そうではないときは、1 ならば 1 を返し、そうでないときはフィボナッチ数列の漸化式にしたがった値を返しています。なお、else 節は省略できます。そのときは、条件が偽であるとき何もしません。
 
このフィボナッチ数の計算は一見シンプルで完璧であるように見えますが、問題があります。それは計算量です。<code>fibonacci(10)</code> はすぐに計算できますが、<code>fibonacci(45)</code> はなかなか計算が終わりません。なぜなら、この関数が呼び出しは自身を2度呼び出すので、2の累乗のオーダーの計算量になってしまうからです。<br />
しかし、実際にフィボナッチ数列を手計算するときは線形時間のはずです。一つ前と今のフィボナッチ数がわかれば次のフィボナッチ数がわかるからです。この考えをコードに起こすには、同じ処理を繰り返さなければならないことがわかると思います。
 
;コード例
<syntaxhighlight lang="D">
import std.stdio;
 
long fibonacci(long n) {
int previous = 0; // F_0
int current = 1; // F_1
int counter = 1; // いま current は F_{counter}
while (counter < n) {
int new_f = previous + current; // F_{n+1} = F_n + F_{n-1}
// 更新
++counter; // counter を 1 増やす
previous = current;
current = new_f;
}
return current;
}
 
void main() {
writeln(fibonacci(10));
}
</syntaxhighlight>
 
;実行結果
55
 
while 文です。
<pre>
while (条件式) {
条件式が真だったときに実行される文
}
</pre>
while 文は、「条件式が真であるなら文を実行し、偽であるならば実行しない」を繰り返す制御文です。
 
== 型 ==