トップ «前の日記(1970-01-01) 最新 次の日記(1970-02-01)» 編集

じじぃの日記、ツッコミ可

Twitter: @jijixi_org
Xbox Live: jijixi

初心者が書いた OCaml 入門
Spotlight tips サイト内リンク集
1970|01|02|
2003|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|11|
2011|05|
2012|01|

1970-01-02 初心者が書いた OCaml 入門 [長年日記]

% [OCaml] 自分のための OCaml 入門

名著「プログラミング作法」のデバッグの章には間違いを見付ける手法として、「自分のコードを他人に説明してみよう」と書かれている。ここでの「他人」は極端な話、テディベアでも良いとされているが、実際これって笑い話では済まない重要なネタである。要は、自分以外のものに説明するためには情報を整理する必要が有って、そうすると今まで見えなかった問題点が見えてくるようになるということだ。

で、デバッグじゃなくても、思考の整理、知識の整理、という作業には上記の方法はとても役立つ。「きちんと理解していないから説明なんかできない」ではなく「きちんと理解していないからこそ説明してみる」という姿勢が、その事柄の理解に大変寄与することであろう。・・・なんで論文調になってるんだ?

そういったわけで、OCaml に関する雑多な事柄をつらつら書いてみますんで、ツッコミポイントを見付けた方はどしどしツッコんでください。

目次

  1. OCaml の基本型
  2. OCaml の変数
  3. OCaml の関数
  4. OCaml の…ってわけでもないけど、末尾再帰
  5. OCaml のスコープ規則
  6. OCaml の分割コンパイル
  7. OCaml の "Objective" なところ
  8. OCaml のイテレータ
  9. OCaml の比較演算子
  10. OCaml の制御構造
  11. 末尾再帰を考える
  12. 一般的なお話(スタック編)
  13. 配列とリストの関係を考えてみる
  14. type 宣言と variant type
  15. polymorphic variant

% [OCaml] OCaml の基本型

わりと C 言語的。ざっと以下のような感じ。

unit     () と書く。C で言うところの void みたいなもの。
int      整数。C レベルの int に対応するが、GC 用のマーカか何かで
         1bit 持ってかれてるらしい(Ruby っぽい)。
         あくまで int なんでアーキテクチャによって bit 数が違う場合があるのが、
         場合によっては微妙かも。そんなときは Int32 モジュールを使うと、
         32bit 整数を保証してくれるらしい(けど重いらしい)。
         大きい数値を使いたいときは、Int64 モジュールを使うと良いみたいです。
float    浮動小数点小数。C レベルの double に対応。
         ちなみに、int <=> float の変換には、int_of_float, float_of_int
         といった関数を使う。
bool     真偽値。true と false の二つ。
char     'a' のようにシングルクォートで囲んだもの。
         整数ではなく、厳密に文字。Python 的。
         char <=> int の変換には、char_of_int, int_of_char 関数をどぞ。
string   文字列。ダブルクォートで囲む。immutable(変更不可)なのが Python 風?
         つーか、OCaml における変数は Ruby と同様に参照なので、破壊的メソッドが
         使えない String クラスって感じで捉えておくと、わりとすんなり…かも。
         "hoge" ^ "fuga" で文字列を連結できます。
追記(訂正やら補足やら)
   int に対応するのは、long のようだ。
   どうして今どき int にマッピングしちゃうかなあ…などと疑問に思いつつも、
   int だと思いこんでたのは、swig が long を int64 に、int を int にマッピングするから。
   まあ、確かに long が 32bit より長い環境だってあるだろうから、わからない話じゃないんだが…
   32bit の long だとしても 1bit 使われて 31bit になっちゃってる問題はあるしなあ。
   あと、その 1bit 使われてるってのは、整数かそれ以外かを示すフラグのようだ。
   そもそも、単なる整数なら GC とか関係無いよな(苦笑
追記その2
   添付モジュールをちろちろ調べてたら……ぬあっ!? string って mutable じゃないですか。
   String.set とか String.fill なんつー関数を使うと見事に中身が書き換えられちまいます。
   じゃあ、なんで immutable だと思ってたかと言うと…マニュアルに、
      "Most Caml data structures are immutable, but a few (most notably arrays)"
   なんつーことが書いてあるんだが、要するにこれ、『いくつかのもの(例えば配列とか)以外の
   大抵の型は immutable なんだよ〜』ってこってしょ?もし string みたいな基本的な型が
   mutable だとしたら、この『配列とか』のところに一緒に『文字列とか』ってのも入る
   もんだと思っちゃうじゃないすか。……ねえ?いや、思い込みといえばそうなんだが……

あと、型とはちょっと違う風味だけど…

tuple    組。Perl とか Python にもあるんで、わりと一般的な概念かと。
         (1, 2. , "hoge") みたいな感じで書きます。トップレベル(対話式インタプリタ)で
         表示される型は、この例だと int * float * string みたいになります。
array    配列。[| 1; 2; 3 |] みたいに書く。この場合の型は int array になる。
         要素の区切りが "," じゃなく ";" なのがちょっと気持ち悪い。つーか間違えやすい。
         ちなみに [| 1, 2, 3 |] とか書いちゃうと、(int * int* int) な tuple が
         ひとつ入った配列ってことになっちゃう。わりとワナ。
         この場合の型は (int * int * int) array になるね。
         ary.(index) って感じで添字指定で要素にアクセスできます。
list     リスト。[1; 2; 3] みたいに書く。この場合の型は int list ね。
         配列と何が違うのかが、わりと微妙。
         添字でのアクセスができない(ランダムアクセスができない?)らしいので、
         C レベルだと単純な連結リストなのかも。
         要素数が少ないときは list 、要素数が多くなったら array って感じで
         使いわけると良いのかねえ?
         そういえば、array も list も要素の型は混在できません。C みたく。
追記その3
   タプル(tuple)の仲間(?)で、record ってのもある模様。いわゆる構造体みたいなもののようだ。
      type hoge = { name : string; number : int };;
   てな風に型の宣言をしておいて…
      let var_hoge = { name = "fuga"; number = 1 };;
   て感じで作る。var_hoge.name とかやると "fuga" が得られたり、ほんとに構造体みたい。
   …それより tuple の使い方がよくわからんのですが、どうしたもんなんでしょうなあ。
   一応、要素が二つの場合は、fst(最初の要素を取り出す)とか snd(二番目の要素を取り出す)
   っていう関数で値を取り出せるんだけど、三つ以上の tuple の場合はどうすんだろ……
   要素三つの tuple を引数に取る関数なんかもあるみたいなんで、値を取り出す方法が
   存在するのは間違いないんだが…つか、ソース見れってこってすか?(苦笑
追記その4
   つーことで、tuple の値の取り出し方を arg.ml から類推。たぶん判明。
   どうやら match ... with 構文を使ってローカル変数に束縛してやるらしいです。
   と言うか、これを追っかけたおかげで、ようやく match 文の意味がわかってきたという(苦笑
   tuple に限らず、match 文の条件式に一時変数名を書いてやると、その条件にマッチした
   時点で、それぞれの値がその変数名に束縛されるらしいです。
      let v_tuple = (1, 2., '3');;  (* val v_tuple : int * float * char = ... *)
      let print_tuple tup =
         match tup with
         | (v1, v2, v3) -> print_endline (string_of_int v1);
                           print_endline (string_of_float v2);
                           print_char v3; print_newline ()
      ;; (* val print_tuple : int * float * char -> unit = <fun> *)
      print_tuple v_tuple;;
      (* stdout に出力 *)
      1
      2.
      3
   こんな感じです。match で tup を調べたときに三つの要素のタプルだったら、"->" 以降の
   処理をするわけだけど、その時にそれぞれ v1 に 1 , v2 に 2. , v3 に '3' が束縛される。
   ちなみにこの例では、処理内容からタプルの各要素の型が完全に推論できるので、
   関数の型は完全に決まってしまい、他の型の引数を与えるとエラーになります。
   型推論ってかっちょいい。

ハッシュ(連想配列)の類が無いけど、基本モジュールにはあるみたい(Hashtbl とかって名前)。

あと今調べたら、list と array の違いは immutable か mutable かってのもあるみたいだね。list は immutable なんで使い捨て、array は mutable なんで使い回す…そんな感じかしらん?

Int32, Int64 を使った整数値は、リテラルで表すとそれぞれ {num}l, {num}L な感じで書ける模様。もすこし具体的に書くと、25 の int32 型表記は 25l (small L) で、int64 型表記は 25L (Large L) てな感じ。Int32.of_int 25 とかやると、25l って値が得られます。

% [OCaml] OCaml の変数

Ruby の場合の変数は、各オブジェクトを表わす構造体へのポインタって感じのイメージ。

void *variable = (void *)ptr_to_struct;

こんな感じ。あくまでイメージよ?まあ、実際のところ Ruby の変数は C レベルでは VALUE っていうポインタなんで、似てると言や似てる。この場合、ptr_to_struct が指す構造体には自分の型(クラス)を示すフラグがあって、実際に使うときにはそれを見て正しい型のポインタにキャストして使う。void * だと缶詰の中に缶切り状態になっちゃってうまくないけど(苦笑

んで、OCaml の場合の変数はと言うと、関数へのポインタっていうイメージで統一しちゃって良さげ。これは高階関数だとかカリー化だとかって概念も関係するんだが、ともかく OCaml においては、例え単なる整数リテラルだとしても、「0 個の引数を受け取り整数を返す関数」と考えてしまえば、最終的に変数に入るものは、全部関数だってことになる。そんで、Ruby と同じように変数はリファレンス(参照)なので、関数へのポインタ…と、こうなるわけですが…イメージできるかなあ。

void *function(void *);
(void *)(*variable)(void *) = function;

ほんとは、void * を返す関数を引数として、同じ型の関数を返す関数…とかにしたいんだが、ややこしいんで却下。つーか、一生懸命書いても、ほんとにあってるか確かめるのがえらく大変そうだし。

ちなみに、OCaml の C レベルレイヤでは、変数は全て value というポインタです。Ruby と似てる。

% [OCaml] OCaml の関数

関数型言語とは何ぞや?と考える。ぶっちゃけて言うと、全てのデータを関数として扱える言語ってなイメージをしてます、わしは。変数のところでも書いたけど、単なる整数値である「1」を…

int one(void) { return 1; }

こんな感じのものとして捉えるわけ。で、こう考えると高階関数だとかカリー化だとかって、よくわからん言葉を持ち出さなくても、仕組みがわかっちゃう。

ちなみに高階関数ってのは「関数を返す関数」らしいが、上に書いたように 1 っていう数値リテラルだって関数だと考えれば、いわゆる普通〜の関数…例えばこんなの…

let f x = x * 2;;

…だって、高階関数じゃないかい?ことさら難しく考えることもないでしょ?

で、次のような複数の引数を取る関数なんかを…

let f x y = x + y;; (* 関数その1 *)

あーそうそう、ここでは数学屋さんが多いと思われる関数型言語使いのみなさんのマネをして、f が関数、x, y, z あたりがパラメータ(引数)って感じで書いてますんで、そのように理解してくださいな。f(x) とかそういうイメージね。

関数を返す関数という概念を利用して、一つの引数を取って一つの値(関数)を返す関数に分割するのがカリー化ってやつ……だと思う。上の例で行くと…

let f1 = f 25;; (* 関数その2 *)

とか書くと、f1 は引数を一つ取り int を返す関数になる。どういうことかと言うと、ちょっと数学的になるんだが…

関数その2の f 25 というのを関数その1にあてはめてみる。
   f x  y = x  + y	なので、
   f 25 y = 25 + y
ということになって、f1 = f 25 だから…
   (f 25) y = 25 + y
    f1	  y = 25 + y
…で、この f1 という関数は、引数 y を取って 25 + y を返すものになると

まあ、数学苦手でも、これくらいはわかるっしょ?

関数その1の型は、「int -> int -> int = <fun>」になるんだけど (「->」ってのは左辺を引数として右辺を返すって意味)、「int -> ( int -> int ) = <fun>」てな感じにカッコで括ってやると上で言ってるようなことがイメージできるんじゃなかろうか。つまり、int を一つ与えると、int を一つ取って int を返す関数が返る…って感じ。うーん、微妙かな。

% [OCaml] OCaml の…ってわけでもないけど、末尾再帰

とりあえず以前に書いたもので良いっしょ。ここっすよ。

% [OCaml] OCaml のスコープ規則

以前 C 並に適当…とか書いたことがあるんだが、さすがにそれは間違いだったようで。現在の理解では、わりと Python に近いような気がする。ファイル一つが自動的にモジュールとしてパッケージされるようになってて、open 命令でモジュールの名前空間をその場に取り込める。

だから、あるモジュール(別のファイル)にある識別子を使いたい場合のアクセス方法としては、

Some_module.some_ident;;
か、
open Some_module;;
some_ident;;

という感じになる。

とりあえず、特に制限しないかぎりは、全ての識別子(変数のところで書いたけど、要はみんな関数なんだから関数のことだと思ってさしつかえない)は public になるわけだけど、ファイルが違うと自動的にモジュールにくるまれるんで、名前がぶつかる心配はほとんど無いでしょう。

ちなみにその自動的に作成されるモジュールの名前は、拡張子を外したファイル名の一文字目を大文字にしたもの。

あとは、関数内で使われる、いわゆるローカル変数について少々。

実は、厳密に言うとローカル変数というものは存在しないらしくて、代わりにローカルスコープを作り出す構文として in っていうのが用意されている。使い方はこんな感じ。

let func1 x =
   let local_var = "hoge" in
   x ^ local_var (* 文字列連結 *)
;;

イメージ的には、local_var が有効なローカルスコープが in の後ろに作られてる感じ。だから、文法とか無視してイメージ的な補完をしてやると…

let func1 x =
   let local_var = "hoge" in {
      x ^ local_var
   }
;;

こんな感じなんだと思う。で、local_var を参照できるのは in 以降のブラケットに囲まれた中だけになる。同様にローカル変数を複数使いたいときは…

let func2 x =
   let local_var1 = "hoge" in
   let local_var2 = "fuga" in
   x ^ local_var1 ^ local_var2
;;

てな感じにネストさせていきます。同じくイメージ的な補完をすると…

let func2 x =
   let local_var1 = "hoge" in {
      let local_var2 = "fuga" in {
         x ^ local_var1 ^ local_var2
      }
   }
;;

こんな感じかね。ただまあ、こんなこときっちり覚えなくても、let variable = value_or_func in でローカル変数の定義だって覚えてしまっても良いとは思うけど。

個人的には、この仕様だとほぼ必然的にローカル変数の定義が関数の頭に集中するので、非常に好みではありますな。C++ のような、どこでも変数の定義ができちゃう言語は、人の書いたコード読むのが疲れます。C++ じゃなく C では最初に書かないとダメなことになってるんだけどねえ……まあ、あれはあれで便利なこともあるのかも知れないが、やっぱ好かんよなあ。必要なものはどっかでまとめて確保するのが良いとは思いませんか?

% [OCaml] OCaml の分割コンパイル

どうも、見当たる入門文書にはこの辺の実際的な説明がほとんどなされてなくて、大変苦労しましたよ、ほんと。つーか、オフィシャルマニュアルですら、この辺のことは説明が足りない気がします。んなわけで、わしが血の小便を流しながら会得した(大嘘…でも、精神的には近いものが)分割コンパイルの際のテクニックを公開しときましょ。

とりあえず、C 言語なんかで複数ファイルのプログラムを作ったことがある人レベルが対象です。それ以下だとよくわからないかも知れないが、勘弁してください。

基本的な流れとしては…

1. 各ファイル(拡張子は .ml)をコンパイル
2. コンパイル済みの各オブジェクトファイル(拡張子は .cmo)をリンクして実行ファイル作成

となるんだけど、案外簡単には行きません。スコープのところでも書いたけど、基本的には各ソースファイルは、それぞれファイル名に応じたモジュールにくるまれています。よって、まずソースを記述する際はスコープのところを参考にして、別のファイルの識別子を使用しましょう。

で、自分のソースファイル内に定義が無い識別子(要するに外部ファイルにある識別子)が記述されていると、そのままではコンパイルができません。コンパイラ(ocamlc)はソース内に未定義の識別子があると、カレントディレクトリとライブラリパス内を調べて、必要なモジュールが記述された .cmi という拡張子のファイルを探します(Some_module が使われていれば some_module.cmi というファイル)。そして、このファイルが見つからないとコンパイルエラーになるわけです。

では、この .cmi というファイルはどこで作られるかと言うと、コンパイルの時に .cmo ファイルと一緒に作られます。つまり依存するファイルから先にコンパイルされるようにしてやらないと、コンパイルができないというわけですね。んで、その依存関係を自分で調べて書いても良いんだけど、そんなのはクールじゃないので、ocamldep というプログラムにまかせましょう。ocamldep コマンドの引数としては、関係のあるソースファイル全てを与えます。ocamldep は結果を標準出力に吐くので、適当なファイルにリダイレクトしてやって保存しましょう。この結果は一般的な Makefile で使える様式になっているので、make を使っているなら Makefile に練り込んでやると楽ですね。

で、依存関係に基いてコンパイル(ocamlc -c)したら、最後にリンクします(ocamlc -o 出力ファイル)。このとき、与えるオブジェクトファイルの順番もまた依存関係に基いて必要なものから先に指定してやらないといけません。けっこういけずです。あと特に順番が関係無くても、C で言うところの main 関数にあたる部分が含まれているオブジェクトは最後に指定しましょう。最後に指定したオブジェクトがトップレベル(グローバルスコープ)になり、そこから処理が始まります。

ちなみにリンク時にも依存関係があるということは、循環参照してたりするとリンク不能だったりするような気がしますが、そもそもまともな設計ならそんなことにはならんと思うので、気にしないどきましょう。

それから、ほっとくと全ての識別子が public だけど、そんなん嫌だぃ必要なものだけ公開したいんだぃぃぃって人は、C のヘッダファイルにあたる .mli ファイルを書きましょう。通常だと .ml の情報から自動的に作成される .cmi ファイルが、.mli があるとそれに基づいて作られるようになるので、このファイルに必要なものだけ書いておけば、ばっちりっぽいです。.mli ファイルの雛形としては ocamlc -i の出力が使えます。

Makefile のサンプルとしては、こんなのがあります。

% [OCaml] OCaml の "Objective" なところ

はっきり言って、クラスの定義なんかも通常の関数とあまり変わりがありません。書式的にはこんなの…

class class_name parameter =
   (* construction phase *)
   let class_variable = 0 in
   (* object definition -> return value *)
   object (self)
      inherit other_class parameter
      val mutable instance_variable = class_variable
      method get_var = instance_variable
      method set_var param = instance_variable <- param + 1
      initializer self#set_var 2
   end
;;

…なんかおよそ現実味の無い例だけど、説明のためってことでひとつ。parameter はインスタンス化するときに使う引数。この例では使ってないけど(苦笑)。もちろん省略可。で、通常の関数定義と同じように、ローカル変数を使うと、それがいわゆるクラス変数のようなものになります。最後に object ... end で囲まれた部分で定義された型のインスタンスが返って終わり。

ぶっちゃけて、使用するときに new 演算子が必要で、返るのが独立したオブジェクト(いわゆるインスタンス)であるということ以外では、実質的な扱いは通常の関数と同じです。なもんでカリー化なんかもできます。複数の初期パラメータを必要とするクラスがあったとして…

(* class hoge : int x -> int y -> int z -> <obj> *)
let new_hoge_func = new hoge 1 2;;
(* val new_hoge_func : int z -> hoge = <fun> *)
let val1 = new_hoge_func 3;;
let val2 = val1;;
let val3 = new_hoge_func 3;;
(* val1 と val2 は同じインスタンス。val3 は別のインスタンス *)

わかる?ここで hoge クラスは三つの引数を取って何らかのオブジェクトを返すわけだけど、二つだけ引数を与えてやると、『引数を一つ取ってオブジェクトを返す関数』になるわけ。

では次にやっと object ... end 内の説明。つってもだいたいわかるような気がするが、self は自分自身に対する束縛名。自分自身を必要とする処理を書くなら適当に名前を付けましょうってこと。必要ないなら省略可。val ... はインスタンス変数の定義。method ... はメソッド定義。initializer には初期化処理を書く。どれもこれも必要ないなら省略可。

クラス変数の部分と initializer の部分の両方で、いわゆるコンストラクタ的な処理ができるが、どう使いわけるべきかは、ようわからん。変数に束縛する必要があるならクラス変数。インスタンスメソッドを呼びたいなら initializer ってとこ?

inherit は継承の指定。継承したいクラスと、そのクラスのインスタンス化に必要な引数を書く。継承になぜ引数が必要なんだ?って気はするが、スーパクラスのコンストラクタを自動で呼ぶようになってて、その処理も同時に書いてるんだ…と思えば許せる?まあ、object ... end の中に書くようになってる点から見て、クラスを継承してると言うよりは、インスタンスを継承してるってイメージなのかもしれないなあ…とか思ったりも。多重継承も可能だそうで、その場合は inherit 行を複数書けば良い。スーパークラスのメソッドを呼びたい時なんかは、inherit 行に as var を加えることで、var を使ってアクセスできる模様。

class a =
   object
      val mutable va = 0
      method get = va
   end
;;
class b =
   object
      inherit a as super
      val mutable vb = 1
      method get = vb   (* オーバーライドも可能 *)
      method get_a = super#get
   end
;;
let obj1 = new a;;
let obj2 = new b;;
obj1#get;;     (* 0 *)
obj2#get;;     (* 1 *)
obj2#get_a;;   (* 0 *)

インスタンス変数は、値を変化させる必要があるなら mutable を指定する必要がある。逆に言えば、定数的に使いたいものは、mutable を付けないでおくと安心。で、値を変えたい時は "<-" を使って代入(?)する(set_var 参照)。ちなみに、何度も言うように変数に束縛するものは何でも関数なんで、

...
   object
      val mutable ivar = fun x -> x + 1
   end
;;

な〜んて書くと、ちゃんと関数を入れることもできたりします(ivar x = x + 1 ... って記法は不可)。メソッド指定してないのでインスタンスメソッドとして呼ぶことはできないけど、オブジェクト内でプライベートメソッド的に呼び出すことはできます。でもまあ、プライベートメソッドの定義方法はちゃんと別に用意されてるんで、そっちを使った方が良いと思うけど(苦笑

...
   object
      method private private_method x = ...
   end
;;

最後にインスタンスの使い方。と言っても、もうすでに上の方に書いてるので全部って気もする。他の言語で "." やら "->" だったりするメソッド指定子(こんな呼び方だっけ?)が、"#" になってるだけです。

% [OCaml] OCaml のイテレータ

Ruby ユーザとしては、list や array の各要素に対して処理をする場合には、イテレータが使いたいと思ってしまうわけで、その辺を調べてみたら、とりあえず List.iter List.map Array.iter Array.map 辺りが使えそう。

それと、OCaml に付属のリファレンスマニュアルって関数の書式の見方(特に例文)がどうにもアレなんで、わしなりの書き方で写しておきます。まあ、関数が "f" で、なんだかわからない型の値は a, b, ... ってのさえわかってれば、なんとかなるんだけど、数学屋じゃないとそんなのいきなり見せられてもピンと来ないよなあ(苦笑

あと、関数の型については、『常に返り値は一つしか無いんだ』ってのを意識すれば、わかりやすくなる。つまり、『'a -> 'b -> 'c -> 'd』って書いてあれば、最後の『'd』が返り値で、残りは全部引数だ。ちなみに『'a』とか『'b』とかってのは多相型で、a とかの文字そのものには意味が無い。『'a -> 'b』となっていれば、何らかの型の引数を受けて、別の(同じでも良いのか?)型の返り値を返す、という意味。で、『'a -> 'a』となっていれば、何らかの型の引数を受けて、引数と同じ型の返り値を返す…となる。

Array.iter :   ('a -> unit) -> 'a array -> unit
List.iter :    ('a -> unit) -> 'a list  -> unit
   配列(リスト)の各要素に、指定した関数を適用する。
   第一引数 → ある型の引数を一つ受けて、unit 型を返す関数
   第二引数 → 第一引数の関数の引数と同じ型の配列(リスト)
   返り値   → unit (返り値無し)
例
・配列の各要素を画面に表示
   let ary = [| "this"; "is"; "a"; "pen" |];;
   let _ =
      let iter_method x = print_endline x in
      Array.iter iter_method ary
   ;;
Array.map :    ('a -> 'b) -> 'a array -> 'b array
List.map :     ('a -> 'b) -> 'a list  -> 'b list
   配列(リスト)の各要素に、指定した関数を適用し、新たな配列(リスト)を作成する。
   第一引数 → ある型の引数を一つ受けて、任意の型を返す関数
   第二引数 → 第一引数の引数と同じ型の配列(リスト)
   返り値   → 第一引数の関数が返す型の配列(リスト)
例
・int のリストを float のリストに変換
   let lst1 = [ 1; 2; 3; 4; 5 ];;
   let lst2 =
      let iter_method x = float_of_int x in
      List.map iter_method lst1
   ;;

ところで _ って変数の説明をしたことがなかった。って言うかわしもちゃんとしたことはわかってないんだが、ともかく、返り値を捨てるような処理をするときに使う習慣(なのか?)らしい。グローバルスコープでの処理なんかで、名前空間を汚さずに処理ができるとか……それくらいしか意味が思いつかないけど、まあ、なんか知らんけど、トップレベルに素で関数呼び出しを書いたりはしないのがお作法みたいですよ?

あと、この _ って記号は match ... with 構文ではデフォルトケースとして使われるんだけど、match 文はまだ勉強が足りないんで、それはまたいずれ。

% [OCaml] OCaml の比較演算子

小ネタですが…ocaml コマンドでインタラクティブに試してみましょう。

# let str1 = "hoge";;
# let str2 = "hoge";;
# let str3 = str1;;
# let lst1 = [1;2;3];;
# let lst2 = [1;2;3];;
# let lst3 = lst1;;
でわ、れっつごー
# str1 = str2;;
- : bool = true
# str1 = str3;;
- : bool = true
# lst1 = lst2;;
- : bool = true
# lst1 = lst3;;
- : bool = true
で、次は
# str1 == str2;;
- : bool = false
# str1 == str3;;
- : bool = true
# lst1 == lst2;;
- : bool = false
# lst1 == lst3;;
- : bool = true

sure? マニュアルによると、= と <> ( = の否定)は "Structural (in)equality test" となっていて、= = と != ( = = の否定)は "Physical (in)equality test" となっている。Structural は構造的、Physical は物質的、てな意味だから、まあ要するに…わかるっしょ?中身を比べて判断するのが = で、外側(つーか泥くさく言うと多分ポインタ値)だけ見て判断するのが = = と、そーゆーこってす。

Ruby で言えば、OCaml の = = は再定義されてない = = のようなもんかな。組み込みクラスの = = は普通ちゃんと再定義されてるんで、OCaml の = のように動くけど、適当に class を作ってまったく同じ内容で別のインスタンスを作って = = で比較してみればわかります。

ちなみに、OCaml においては int 型だけは C レベルでも(ほぼ)素の値が使われるんで、

# let i1 = 1;;
# let i2 = 1;;
# i1 = i2;;
- : bool = true
# i1 == i2;;
- : bool = true

てなことになりますね。まあ、なにはともあれ、通常は等値比較は "=" と "<>" を使っときゃ良いんじゃないでしょうか。

% [OCaml] OCaml の制御構造

ぶっちゃけ、if の話。あと in とか match についてもちょっと。いくつか用意されている制御構造の中で、if だけがちょっとクセがあるみたいなんで、解説してみます。

まずは(関数型言語としてはちょっと邪道らしいんだが) for とか while の場合を見てもらいましょう。ちなみに print_endline ってのは文字列を、改行を付加して標準出力に吐く関数で、string_of_int ってのは int の値を string (文字列)に変換する関数ね。

(* for *)
for i = 1 to 10 do
   print_endline (string_of_int i)
done
(* while *)
let i = ref 1 in
while !i <= 10 do
   print_endline (string_of_int !i);
   incr i
done

どちらも 1 から 10 までカウントアップして、その時点のカウント変数の値を画面に表示してます。

…と、細かい説明の前に、リファレンスの説明をしてなかったと思うんで、少ししておきましょう。リファレンスってのは、while ループの手前で変数 i に束縛している値( ref 1 )のことなんだが、要するにこれって何かと言うと、mutable な変数です。

OCaml の変数は基本的には immutable (書き換え不可)なので、ループ変数のような『破壊的』に値が変わっていく必要がある変数には、こういった mutable (書き換え可能)なものを使ってやる必要があるわけ。

まあ、いわゆる『ポインタ』だと思ってればだいたいオッケーで、

int ri = 1
int *i = &ri;
while ( *i <= 10 ) {
   printf("%d\n", *i);
   (*i)++;
}

上の while ループを C で書くとこんなイメージかな。ポインタを手繰り寄せて実体を参照する演算子( C では * )が、! で、incr ってのはリファレンスが指している先の int の値をインクリメントする関数。普通に値を書き換えるなら := 演算子を使う。

本題に戻って、先の for や while を見てください。制御構造によって実行(ループ)される部分ってのが do ... done に囲まれてるから一目瞭然だね。それから、一種の制御構造みたいなものとして、in や match なんてのもあるけど、これらの場合は、

(* in *)
let tmp = 1 in
print_endline (string_of_int tmp);
print_endline (string_of_int (tmp + 1));;
(* match *)
let f x =
   match x with (* x を num というローカル変数に束縛している *)
   | num -> print_endline (string_of_int num);
            print_endline (string_of_int (num + 1))
;;
f 1;;

こんな風に書いてると、in の場合も match の場合もどちらも 1\n2\n と表示されます。つまり、構文の終了( ;; )まで効果(スコープ?)が生きてるわけ。うー、説明下手だなあ(苦笑)。んで、次にいよいよ if 文で似たようなことを書いてみます。

(* if true *)
let tmp = 1 in
if true then
   print_endline (string_of_int tmp);
   print_endline (string_of_int (tmp + 1))
;;

どうでしょう……ちゃんと 1\n2\n が表示されますね。でもちょっと待った。こうするとどうでしょうか?

(* if false *)
let tmp = 1 in
if false then
   print_endline (string_of_int tmp);
   print_endline (string_of_int (tmp + 1))
;;

if true の結果からすると、何も表示されずに終わるように思えます……が、実は 2\n が表示されちゃいます。実はこれ、インデントが嘘で、実際には…

(* if indent right *)
let tmp = 1 in
if false then
   print_endline (string_of_int tmp);
print_endline (string_of_int (tmp + 1))
;;

こういうことなのですな。つまり、if 文は tmp を表示する部分で終わっていて、tmp + 1 の表示は if の結果にかかわらずされてしまうのです。要するに、then の後の部分、あるいは else の後の部分で複数行に渡る処理をしたいときは、なにがしかのブロック構造にしてやる必要があるのです。よって、先の例でいけば…

let tmp = 1 in
if false then
   begin
      print_endline (string_of_int tmp);
      print_endline (string_of_int (tmp + 1))
   end
;;
もしくは…
let tmp = 1 in
if false then (
   print_endline (string_of_int tmp);
   print_endline (string_of_int (tmp + 1))
   )
;;

…のようにしてやると、想定した結果(何も表示されない)が得られます。また、先に述べたとおり、in や match は ;; (もしくは次の構文の先頭。ちゃんとした言い方がわからんので、詳しくは述べないでおくが、今回の場合は else が来ても止まる)が来るまで有効なスコープ(というかブロック?)を作り出すので、then 以降の部分でこれらを使ってやると、同じような効果が得られますね。

if false then
   let tmp = 1 in
      print_endline (string_of_int tmp);
      print_endline (string_of_int (tmp + 1))
;;

こんな感じに。ちなみに match はある値に任意の名前を付ける用途にも使えるので、活用してみましょう。場合によっては let ... in を使うよりわかりやすく書けることもある気がします。match のより詳しい使い方は、またいずれ……

% [OCaml] 末尾再帰を考える

C なんかで普通に for でループさせちゃうような処理があるとして、それをいかにして末尾再帰を使った方法に変換するかを研究してみようと思った。ほんとは関数型言語を使うなら最初から for ループが頭に浮かぶようじゃダメなのかも知れんが、そう簡単には頭の切り換えなんてできないしねえ。

ともあれ、わしが考える末尾再帰の(とくに for の代替としての)コツは、カウント変数に相当するカウント引数とでも呼ぶものを持たせること(これは前にも書いた)と、最終的な目的の値と同じ型の引数を持たせることである。

まずはカウント引数の簡単な例を示してみよう。

/* C */
int i;
for (i = 0; i < 10; i++) {
   printf("%d\n", i);
}
(* OCaml : for *)
for i = 0 to 9 do
   print_endline (string_of_int i)
done;;
(* OCaml : tail-recursive *)
let rec trfunc i =
   match i with
   | 10	 -> ()
   | num -> print_endline (string_of_int num);
	    trfunc (num + 1)        (* ここで再帰 *)
;;
let _ = trfunc 0;;

さあ、どうでしょう、ピンと来ましたか?どれも 0 から 9 までの数字を端末に吐き出す動作をします。再帰関数を定義するときは関数名の前に rec を付ける必要があるので注意しましょう。

ちなみに、ここでは再帰関数を抜けるときの値を他の例に合わせる意味で 10 と設定してますが、通常はここを 0 にして…

let rec trfunc i =
   match i with
   | 0   -> ()
   | num -> print_endline (string_of_int num);
	    trfunc (num - 1)
;;
let _ = trfunc 10;;

…みたいにしておくのが無難でしょう。ただしこの例だと表示される順番が逆になっちゃいますが、現実的なプログラムでそれが問題になることは稀じゃないかと。んで、こういう風に書いておけば、ループさせたい回数が変わっても、最終的な trfunc の呼び出しのところだけ直せば用が足ります。

とりあえず、カウント引数の使い方は理解できたでしょうか。つぎに、もうちょっとだけ現実的な例を出しましょう(といっても、やっぱり作為的ではあるが)。

ここでは、要素数が 10 で、その全てを 0 で埋めたリストを作ってみます。リストは immutable なんで、for の例ではちょっとズルしてリファレンス使います。

(* for *)
let lst = ref [];;
for i = 1 to 10 do
   lst := 0 :: !lst
done;;
(* tail-rec *)
let rec trf i li =
   match i with
   | 0 -> li
   | n -> trf (n - 1) (0 :: li)     (* ここで再帰 *)
;;
let lst = trf 10 [];;

ここで、:: (コロンが二つ)という演算子は、左辺に指定した要素を、右辺に指定したリストの頭に付け足したリストを返します。

この例での特徴は、カウント引数の他に、処理の対象となるもの(ここではリスト)をまるまる関数に与えてやってるところ。そして、最終的な呼び出し時には、ループさせる回数と、最終的に欲しい値のいわば種とでもいうもの(ここでは空のリスト)を与えてやります。再帰呼び出しされるごとにカウント引数は 1 ずつ減っていき、0 になったらその時点でのリスト(再帰時に与えられた引数)をそのまま吐き出して終了。

これだけだと、ちょっとわかりづらいかも知れないんで、実際の処理がどう進んでいくのかを追ってみますかね。

1. 最初の呼び出し → trf 10 []
2. i が 0 じゃないので再帰 → trf (10 - 1) (0 :: []) → trf 9 [0]
3. 以下 i が 0 になるまで……
   trf (9 - 1) (0 :: [0]) → trf 8 [0; 0]
   trf 7 [0; 0; 0]
   trf 6 [0; 0; 0; 0]
   trf 5 [0; 0; 0; 0; 0]
   trf 4 [0; 0; 0; 0; 0; 0]
   trf 3 [0; 0; 0; 0; 0; 0; 0]
   trf 2 [0; 0; 0; 0; 0; 0; 0; 0]
   trf 1 [0; 0; 0; 0; 0; 0; 0; 0; 0]
4. trf 0 [0; 0; 0; 0; 0; 0; 0; 0; 0; 0]
   i が 0 なので、再帰せずに引数をそのまま返しておしまい

末尾再帰ってのは要するに再帰呼び出しした結果を知る必要がない再帰のしかたです。やっぱうまく説明できんな。通常の再帰は再帰呼び出しして得た結果を使って、さらに処理をしたりするもので、だから当然呼び出し元の状態は維持されなきゃならない。よってスタックを積まないと処理が続けられない。で、末尾再帰は再帰呼び出しをした時点で、(結果を知る必要がないから)呼び出し元の状態は維持する必要がないわけで、結果、スタックに積む必要もないということになる……んだが、やっぱきれいに説明するのって難しいねえ。

……誰でも手軽にプログラムができるこのご時世、スタックって何?とか思いながらプログラム書いてる人間も結構いそうなのが怖いところ。つーわけで、次は番外編としてスタックについて…書くかなあ。

% [OCaml] 一般的なお話(スタック編)

そもそもの意味でのスタック(stack)とは、バッファリング(一時的に溜めておいたりする行為…で良いのかな)などに使うデータ構造の一種。FILO バッファなんていう呼び方もある…かな。お仲間には FIFO バッファ、別の言い方だとキュー(queue)というのもありますな。ちなみに FILO だとか FIFO だとかってのは First In Last Out (あるいは First In First Out)の略で、最初に入ったものが最後に出てくる(もしくは、最初に入ったものが最初に出てくる)という意味ですね。まあ、この辺は情報処理教育を受けた人ならまず習ってるんじゃないかと……思うんだけど、どうなの?とりあえず基本情報技術者試験とか受ければ、大抵問題に出てくるでしょ。

んで、C を始めとする、関数(言い方は何でも良い。メソッドでもサブルーチンでも)によって処理の抽象化を行うプログラミング言語では、その関数呼び出しの仕組みに、ほぼ例外なくスタック構造が使われています。

ところでスタックを「積む」という表現はどっから来るもんなんでしょうな。わしも自然と使ってるけど。まあ、大抵スタック構造の説明をするときは、箱のようなものに上からものを入れていって、出すときは上に積まさったものから出していく…みたいな絵が入るんで、そういうもんなんでしょう。別に違和感があるわけじゃないし、むしろしっくり来る言い方だから良いんだけどね(苦笑

話を戻して、関数の呼び出し。通常、関数を呼び出すときには、その関数の処理が終わった後に、その呼び出した箇所以降の処理が続いてくれないといけない。処理が続くためには何が必要かというと、その時点での状態……まあ泥くさく言ってしまえばメモリの内容……が維持されないといけないわけです。

直前の状態を保持したまま(つまりそこには手を付けずに)、別の(要は呼び出した関数内の)処理をしなければいけないので、そのための新たな領域を確保します。これが「スタックを積む」という動作です。スタック構造というのはメモリを線形に使う(というか使いまわす)のに有利な構造で、特定の位置から必要な分をざーっと確保していって、その確保した領域で行う処理の最後で、記憶しておいた元の位置に戻るようにしておけば、必要がなくなった部分を簡単に捨てて、次はまたそこから確保することで簡単に使いまわせるわけです。ほんと説明下手だな。つーか絵でも無いと説明できんわ。気になる人はその手の本でも読んでください(泣

さて、そこで OCaml の末尾再帰の話。OCaml では(というか大抵の関数型言語はそうらしいが)、末尾再帰されている場合はスタックを積まずに処理するように最適化されます。まあ要するに、通常なら再帰呼び出しした時点で新たにスタックを積んで、そこで処理をする(のでメモリをバンバン消費する)ところを、現在の場所(再帰なんだから、引数の内容が違うだけで同じ関数なわけだ)を再利用する形で処理をするということでしょう。

% [OCaml] 配列とリストの関係を考えてみる

わしのヌルい頭では、わりと永遠の謎っぽい配列とリストの使い分けについて、考えてみたい。

Array モジュールと List モジュールに登録されている関数を見比べてみると、なんとなくだが方向性が見えてくる。これらのモジュール間での一番大きな違いは、ソートとサーチだろう。Array と List の sort 関数 (と、類似の関数) では、微妙に使い方(?)が違う。Array.sort は元の配列を破壊的に書換える。List.sort はソートした新たなリストを返す。まあ、array が mutable で list が immutable だと知っていれば、間違うことも無いだろうけど。

んで、List モジュールにあって Array モジュールに無いものとして、for_all や exists などのスキャン用関数や、find や filter などの検索用関数、ハッシュテーブル的に使える (と思われる) assoc や assq といった関数などがある。これらは index (添字) が重要でない場合 (リストを単に集合として扱う場合) に特に便利だろう。

逆に Array にあって List に無いものとしては、make や init などの任意の値で初期化した配列を作成する関数や、iteri や mapi といった添字込みで処理するイテレータ、その他 fill などの破壊的な操作を行う関数などがある。

この辺から判断するに、通常はリストを使うのが便利なんだろうと思う。map なんかも順番にこだわらないなら末尾再帰バージョンの rev_map が使えて効率的だと思われる。で、添字が重要な場合や破壊的操作が必要なときには配列を使う。添字が重要な場合ってのはパッと思い付かないけど、破壊的な操作が必要なとき (と言うか、その方がすっきりしてるとき) というと、例えば多次元配列を使う場合なんか。

let data = [|
   [| 2; 4; 1; 3; 0|];
   [| 0; 3; 2; 4; 1|];
   [| 1; 3; 4; 0; 2|];
|];;

…みたいな二次元配列 (配列の配列) があったとしよう。このとき、この配列の任意の行をソートしたい場合、

(* 一行目だけソート *)
let _ = Array.sort compare data.(0);;

こんな感じで済むわけだけど、もしこれがリストのリストだったとしたら、

(* 他にもやりようはあるだろうけど…
 * どっちにしても、配列並に簡潔に書くのは難しそう *)
let item = List.nth data 0;;
let tmp = List.sort compare item;;
let filter_method i = if (i == item) then false else true;;
let data = tmp :: (List.filter filter_method data);;

こんな感じでややこしい。これ以外でも、ほんの一部分だけを変更するというのが基本の動作の場合、リストで扱うのは手間の点でも、(おそらく) メモリ効率の点でも無駄がありすぎる。そういったときには配列を使うべきなんでしょう。

ということで、結論としては……通常はリスト、ところにより配列、となるでしょう……たぶん。

% [OCaml] type 宣言と variant type

今回は type の使い方について考えてみる。基本的な type の使い方はぶっちゃけて言って、C における typedef だ。

# type hoge = int;;
type hoge = int
# let f (x : hoge) = print_int x;;
val f : hoge -> unit = <fun>
# f 1;;
1- : unit = ()

ここでは hoge という型を宣言しているが、これは int のことなので、print_int に素直に渡すことができる。こういった形での使い方については、C の typedef と同じように考えていけるので、詳しい説明は省く。また recode 型を宣言する場合にも type を使うが、その場合の書き方については、このページの上の方にある追記3辺りに例がある。

さて、そしていよいよ本題の variant type である。日本語で言うと多態型などと言われるものだ。誤解を恐れず言えば、概念的には C における union (共用体) のようなものだと思う。あるいは Java における interface のようなものか。なんだかわからんな。ともかく、関数にいわゆる polymorphism を持たせるために使うものだ (ただし OCaml では、polymorphic, polymorphism という言葉はちょっと別の意味で使われているので注意) と言える…と思う。

厳密な型付けが行なわれる OCaml では、例えばこんな関数は作ることができない。

# let print_num x =
     match x with
       (i : int) -> print_int i
     | (f : float) -> print_float f;;
This pattern matches values of type float
but is here used to match values of type int

意図としては、引数が int であれば print_int 、float であれば print_float を適用する関数を作りたいわけだが、これは許されない。ちなみに、次のようなものは許される (これが OCaml における polymorphism)。

# let pass x = x;;
val pass : 'a -> 'a = <fun>

要するに、関数の中身に、引数の型を限定してしまうような要素が無い場合には、引数の型は何でも良いわけだ。ただしこの例の場合は引数をそのまま返すわけだから、引数の型は何でも良いけど、返り値は引数と同じ型ですよ、という型の関数になっている。こういうのは、日本語では多相型の関数などと言われているようだ。

んで、話を戻す。さっきの例のように、引数の型によって処理が分岐する一つの関数を作りたい場合に variant type は活躍する。つまり引数の型が一つに決まっていれば良いわけだから、いろいろな型を含む一つの型を作って、それを引数にすれば良いのだね。

# type num = 
       Int of int
     | Float of float;;
type num = Int of int | Float of float
 
# let print_num x =
     match x with
       Int i -> print_int i
     | Float f -> print_float f;;
val print_num : num -> unit = <fun>
 
# print_num (Int 1);;
1- : unit = ()
# print_num (Float 1.);;
1.- : unit = ()

こんな感じ。ここで使われている "Int" や "Float" というのは constructor と呼ばれるもので、最初が大文字でなければならない。コンストラクタと言うと、C++ や Java で new したときに呼ばれるものというイメージがあるが、まあ意味は一緒だよね。あちらは『インスタンス』を作るもので、こちらは『ある型の値』を作るものだ。

また、関数と同じように、variant type を多相型にすることもできる。これを polymorphic variant と言う。(言わねえ〜!!確かに polymorphic な value を使った variant なんだけども、polymorphic variant と呼ばれるものは別にあるそうです...orz) polymorphic も variant も似たような意味な気がするんで、なんか変な呼び方って気はするけど(苦笑

# type 'a point =
       Type1 of (int * 'a)
     | Type2 of (float * 'a);;
type 'a point = Type1 of (int * 'a) | Type2 of (float * 'a)
 
# let print_point x =
     match x with
       Type1 (i, _) -> print_int i
     | Type2 (f, _) -> print_float f;;
val print_point : 'a point -> unit = <fun>
 
# print_point (Type1 (1, "hoge"));;
1- : unit = ()
 
# print_point (Type2 (1., 'c'));;   
1.- : unit = ()

実はこれの何が嬉しいのかイマイチ理解できていないので、例は無理矢理でっち上げたものだ。嬉しい使い道は各自考えてください。わしにはよくわかりません(爆

% [OCaml] polymorphic variant

本当の polymorphic variant と言うものをご紹介いたしますです、ハイ...orz

普通の variant の場合は、使う前に type 宣言しておく必要があるわけですが、polymorphic variant の場合は、なんといきなりコンストラクタ(variant tag と言った方が良いようでもある)を使ってしまえるのです。そんでもって、それが実際どんな型なのかについては、どんな風に使われてるかを見て型推論してくれるというすぐれもの。

なので、上の例で挙げた print_num 関数なんかは、いきなりこんな風に書けちゃいます。

# let print_num x =
     match x with
       `Int i -> print_int i
     | `Float f -> print_float f;;
val print_num : [< `Float of float | `Int of int ] -> unit = <fun>
 
# print_num (`Int 1);;
1- : unit = ()
# print_num (`Float 1.);;
1.- : unit = ()

という具合。type 宣言は必要ありません。タグ名の頭にバッククォートが付いてるのが polymorphic の印。

[ ] に囲まれている部分が型宣言の代わりなわけだけど、頭に付いてる "<" てのが不思議ですね。どうやらこれは、完全な型としてできあがっていることを示しているようです。いまいちよくわかりませんね。要するに、この関数では `Float と `Int 以外の引数はあり得ないということです。逆に次のような形だと…

# let print_num2 x =          
     match x with               
       `Int i -> print_int i      
     | `Float f -> print_float f
     | _ -> ();;
val print_num2 : [> `Float of float | `Int of int ] -> unit = <fun>
 
# print_num2 (`String "s");;
- : unit = ()

型のところに今度は ">" が付いてますね。これは型がはっきり決まってないよということです。具体的には `Float と `Int 以外の型が引数として使われる可能性があるということですね。

さて、polymorphic variant の特徴としておもしろいことがあって、変数(関数)に束縛した時点でその型は独立しています。つまり…

# let f1 x =
     match x with
       `Hoge i -> print_int i
     | `Fuga f -> print_float f;;
val f1 : [< `Fuga of float | `Hoge of int ] -> unit = <fun>
 
# let f2 x =
     match x with
       `Hoge f -> print_float f
     | `Fuga i -> print_int i;;
val f2 : [< `Fuga of int | `Hoge of float ] -> unit = <fun>
 
# f1 (`Hoge 1);;
1- : unit = ()
 
# f2 (`Hoge 1.0);;
1.- : unit = ()

同じ名前の `Hoge というタグが、f1 と f2 で意味が違っているわけです。 ともあれ、なかなか便利そうな polymorphic variant なんで、いろいろ使ってみよう。うむ。

本日のツッコミ(全2件) [ツッコミを入れる]
% Q太郎 (2006-07-02 10:54)

大変楽しく読ませていただきました。<br>本家の英語ドキュメントは、サンプルコードが<br>作りこまれていて、入門者をまったく想定していないですね。さて、ref のリファレンスですが、C言語の<br>ポインタとしてみると、参照先の値が変わらないのです。<br>let i = 1;;<br>let j = ref i;;<br>j := 2;;<br>としても、元のi の値は 1 のままなので、<br>ref は初期値として値をもらうという解釈で<br>いいのでしょうか?

% jijixi (2006-07-02 16:33)

まあ、そういうことですね。<br>参照しているのは変数じゃなく、あくまで値です。<br>ポインタに例えたのは、あんまり良くなかったかも。

お名前:
E-mail:
コメント:

トップ «前の日記(1970-01-01) 最新 次の日記(1970-02-01)» 編集

日記ってのは本来、自分で読み返すためにあるもんだよなあ……
もしくは有名人になったら死後に本になったりとかか?

RSS はこちら

jijixi at azito.com