1. nak2yoshi

    No comment

    nak2yoshi
Changes in tags
Changes in body
Source | HTML | Preview
@@ -1,207 +1,225 @@
* 以下のコードは、dmd2.067.1で動作を確認しました。
* D言語を使っていて気づいた、他愛のないことを書いています。
* __まあたらしい内容はありません__、ご注意ください
# __配列の全要素を表示する(ループ)__
配列の中身を表示するのを愚直にやると、
ブラケットで囲って、ループで回して、要素をカンマで区切って、
こんな感じでやると思います。
```D:D
import std.stdio;
// 一次元配列の表示関数
void writeArray(int[] arr)
{
"[".write;
foreach (elem; arr[0 .. $ - 1])
{
elem.write;
", ".write;
}
arr[$ - 1].write;
"]".write;
}
// 二次元配列の表示関数
void writeMatrix(int[][] mat)
{
"[".write;
foreach (elem; mat[0 .. $ - 1])
{
elem.writeArray;
", ".write;
}
mat[$ - 1].writeArray;
"]".write;
}
void main()
{
auto arr = [0, 1, 2, 3, 4];
auto mat = [[0, 1], [2, 3], [4, 5]];
arr.writeArray;
writeln("");
mat.writeMatrix;
}
```
```:Output
[0, 1, 2, 3, 4]
[[0, 1], [2, 3], [4, 5]]
```
# __テンプレート化(再帰+ループ)__
ここで`writeArray`と`writeMatrix`は、構造がほとんど同じなので
テンプレート関数を使って一つにまとめます。
`std.traits`の`isArray`テンプレートを使用して、
配列かそうでないかの場合分けをしています。
```D:D
import std.stdio, std.traits;
// 多次元配列の表示関数
void writeMatrix(M)(M mat)
{
void writeArray(A)(A arr)
{
static if (isArray!A)
{
"[".write;
foreach (elem; arr[0 .. $ - 1])
{
writeArray(elem);
", ".write;
}
writeArray(arr[$ - 1]);
"]".write;
}
else
{
arr.write;
}
}
writeArray(mat);
writeln("");
}
void main()
{
auto arr = [0, 1, 2, 3, 4];
int[2][3] mats = [[0, 1], [2, 3], [4, 5]];
auto matd = [[0, 1], [2, 3], [4, 5]];
arr.writeMatrix;
mats.writeMatrix;
matd.writeMatrix;
}
```
```:Output
[0, 1, 2, 3, 4]
[[0, 1], [2, 3], [4, 5]]
[[0, 1], [2, 3], [4, 5]]
```
次元を下げながら再帰をしていき、配列ではなくなったら
値を表示するという処理の流れです。
テンプレート化の効能として、多次元、及び静的配列にも対応することができました。
(ネスト関数をUFCSできないのが悔しいですね。。。)
# __文字列操作バージョン__
構造はずいぶんスッキリしましたが、
都度、標準出力に`write`しているのはイケてない気もします。
表示する内容の文字列をあらかじめ作成しておき、
最後に`writeln`するように変更してみましょう。
```D:D
import std.stdio, std.traits, std.conv;
void writeMatrix(M)(M mat)
{
string result;
void inner(A)(A arr)
{
static if (isArray!A)
{
result ~= "[";
foreach (elem; arr[0 .. $ - 1])
{
inner(elem);
result ~= ", ";
}
inner(arr[$ - 1]);
result ~= "]";
}
else
{
result ~= arr.to!string;
}
}
inner(mat);
result.writeln;
}
```
# __やったか?!__
`std.string.join`で、ブラケットとカンマ区切りの加工を行い、
`std.string.map`で、ループ処理をすればもっと簡単になりそうです。
```D:D
import std.stdio, std.traits, std.conv, std.string, std.algorithm;
void writeMatrix(M)(M mat)
{
string inner(A)(A arr)
{
static if (isArray!A)
return ["[", "]"].join( arr.dup.map!( elem => inner(elem) ).join(", ") );
else
return arr.to!string;
}
inner(mat).writeln;
}
```
※`dup`がないと静的配列の場合にエラーになるようです。
なにはともあれ、よかったよかった。
# __あ、手がすべっtt__
「あっ」
```D:D
import std.stdio;
void main()
{
auto arr = [0, 1, 2, 3, 4];
int[2][3] mats = [[0, 1], [2, 3], [4, 5]];
auto matd = [[0, 1], [2, 3], [4, 5]];
arr.writeln;
mats.writeln;
matd.writeln;
}
```
```:Console
[0, 1, 2, 3, 4]
[[0, 1], [2, 3], [4, 5]]
[[0, 1], [2, 3], [4, 5]]
```
__「・・・」__
__「・・・」__
__「(普通にwritelnで出るじゃん・・・)」__
+
+__※↓2015.07.27追記__
+__コメントでwriteflnを使う方法を教えて頂きました。__
+
+```D:D
+auto matd = [[0, 1], [2, 3], [4, 5]];
+writefln("%(%(%d %)\n%)", matd);
+```
+
+
+```:Output
+0 1
+2 3
+4 5
+```
+
+__「(writefln、かしこい・・・!)」__
+
# __結論__
__D言語の`writeln`関数は、多次元配列も表示してくれます。__
__とても便利! 皆さんどんどん使いましょう!__
# __次回、「to!(int[])に死す」。デュエルスタンバイ!(続きません)__