プログラミング言語 Red 入門記 #2 Redの基本

# サンプルコードの解説
以下の[前回の記事](http://qiita.com/koba-a-koba/items/23a227e1b4dadfc2849b)のコードをベースにRedにおけるコーディングの基本的な部分や構文などについて解説をしていきます。

``` check-folder-or-file.red
Red []

dir: request-dir
files: read dir

show-file-or-folder: func [ files [block!] ] [
	foreach file files [
        print [form file "is" either dir? file ["folder"] ["file"] ]
	]
]

show-file-or-folder files
```

## パート１：プログラムのヘッダー
1行目はRedのヘッダー部分です。
本来はアプリ名や作成者名などを記載しますが、今回は省略しています。

## パート２：フォルダ選択ダイアログの表示
2行目は以下のようになっています。

``` check-folder-or-file.red
dir: request-dir
```

dirはいわゆる変数のようなものですが、Redではwordと呼びます。
wordは初めて使うときでも特に初期化の構文はなく、いきなり任意の名称を書けばOKです。
コロンがいわゆる代入のような（C#などでの「=」に似たもの）もので、
ここではdirというwordにrequest-dirの結果をセットしています。
request-dirは組み込みの関数で、フォルダの選択ダイアログを表示して、選択結果を戻り値として返します。

## パート３：選択したフォルダの中身の読み込み
次の行は以下のようになっています。

``` check-folder-or-file.red 
files: read dir
```

これも前の行同様、「files」というwordにreadの結果をセットしています。
readも組み込みの関数で、フォルダパスを受け取って、そのフォルダの中身を取得します。

readに渡しているのが１行前でrequest-dirの結果をセットしたword、dirです。
これでfilesにread関数の結果がセットされます。
なお、Redでは関数呼び出しの時に( )はつけず、また引数を区切る時にカンマなどを使うこともありません。
どちらも半角スペースを空けることで表現します。
引数が複数ある場合はそれぞれ半角スペースを入れることになります。

## パート４：関数を作る
次の行あたりがRedっぽさが出てきますが、関数の定義を行っている部分になります。

``` check-folder-or-file.red
show-file-or-folder: func [ files [block!] ] [
	foreach file files [
        print [form file "is" either dir? file ["folder"] ["file"] ]
	]
]
```

show-file-or-folderが作った関数を受け取っているwordです。
Redでは関数を定義する時に専用の構文は使わず、関数オブジェクトを作ってそれをwordに代入する、というやり方をします。
そして、関数を作るために使っているのがfuncという関数です。[^1]
コンソールで「? 関数名」と打つと使い方を見ることができるため、以下のようにfuncの使い方を確認してみます。

> red>> ? func

上記のコマンドを実行すると、以下の説明が表示されました。

> USAGE:
>     func spec body
>
> DESCRIPTION:
>      Defines a function with a given spec and body. 
>      func is of type: native!
>
> ARGUMENTS:
>      spec  [block!]
>      body  [block!]
>
> REFINEMENTS:

引数（ARGUMENTS）が２つで、両方ともblock!型であるとなっています。
block!は複数の要素を持てる配列とかタプルのようなものです。
Redでは[ ]がblock!を意味します。[ ]の中に[ ]が入ることもあります。
今回のソースではfuncに以下の２つのblock!を渡しています。

``` check-folder-or-file.red
[ files [block!] ]
```

``` check-folder-or-file.red
                      [
foreach file files [
  print [form file "is" either dir? file ["folder"] ["file"] ]
]
```

それぞれについて説明します。

### 関数のシグネチャの定義
funcに渡しているblock!の１個目はC#などで言うメソッドシグネチャを記載するblock!で、ここでは引数としてfilesというwordがあり、型がblock!だと指定しています。[^2]

### 関数本体の定義
渡しているblock!の２個目が関数の処理の本体部分です。
ここは割と他の言語と似た感じなのでイメージつきやすいかと思いますが、
foreachは２つ目の引数（files）の中身を順番に列挙して１つ目の引数（file）に格納し、
そのたびにblock!の中身を実行する関数です。
「foreach **文**」ではなく関数の一種なのが面白いところです。
printは標準出力への文字列表示ですが、渡しているのはまたしてもblock!です。
中で使っている関数を知らないと分かりにくいかもしれないですが、
このblock!は意味的には以下の３つのパートに分かれています。

> form file
> "is"
> either dir? file ["folder"] ["file"]

１つ目のパートのformは渡されたwordの中身をフォーマットして文字列化する関数です。
Redだとfile!データ型が若干独特の文字列表現になりますが、
formを通すと一般的な感覚のパスになります。

２つ目のパートは、単純な文字列リテラルの「is」です。

３つ目のパートのeitherはいわゆるifで、第１引数がtrueなら第２引数、
falseなら第３引数のblock!の結果を返すようになっています。
第１引数はdir? fileという関数呼び出しになっていて、
これはfileがフォルダであるかをチェックしています。

これをprintで文字列化すると、以下のような出力が得られます。

> XXX is file ; XXXがファイルだった場合

または

> YYY is folder ; YYYがフォルダだった場合

block!の中身は半角スペースで区切られますが、printするとそのまま
スペース区切りで出力されるので、上記のような出力になってくれます。

## パート５：作成した関数の呼び出し
さて、サンプルの最後は以下の１行になります。

``` check-folder-or-file.red
show-file-or-folder files
```

厳密にはshow-file-or-folderもfilesもwordな訳ですが、直感的に言えばここは
show-file-or-folder関数に引数としてfilesを渡している、という理解でよいかと思います。

随分長くなってしまいましたが、これでサンプルコードの説明が終わりました。
次回からまた色々試してみたいと思います。

[^1]: 他にも定義の仕方があるようですが、今のところfuncが一番楽なのだと認識しています。厳密にはfuncはfunction!型ではなくnative!型のようなのですが、ちょっとその二つの違いがまだ分かっていません。
[^2]: どうも[block!]という記載を他のデータ型にしても動いているっぽいのですが、理由がよく分かっていません。調査中です。