Schemeを覚える3(入出力1)
今日はファイルの読み込みのみ。
Scheme 入門 9. 入出力にあるコードを読み解く。
> (define (read-file file-name) ;関数の定義 (let ((p (open-input-file file-name))) ;p変数に入出力ポートを設定 (let loop((ls1 '()) (c (read-char p))) ;名前つきletでループ、ls1を空のリストで初期化、cをポートから読みとった一文字で初期化 (if (eof-object? c) ;cがファイルの終端かどうか判断 (begin ;begin内の処理をまとめて行う (close-input-port p) ;入出力用ポートを閉じる (list->string (reverse ls1))) ;ls1リストに入っている文字列を”逆順で”出力 (loop (cons c ls1) (read-char p)))))) ;新しいリストを作る(セットされる文字は常にリスとの先頭に。つまり逆順でリストに追加されていく)。次の文字を読み込み。
これを実行した結果が
> (read-file "/home/hironemu/hello.txt") "Hello world!\nScheme is an elegant programming language\n" > (display (read-file "/home/hironemu/hello.txt")) Hello world! Scheme is an elegant programming language
と、このようにファイルの内容が出力される。そういえば名前つきletを勉強してなかったなー。
(let loop((ls1 '()) (c (read-char p)))
この行で、変数の初期化する部分にloopって名前をつけておき、局所変数ls1とcを初期化しておき
(loop (cons c ls1) (read-char p))))))
この行で、さっき名前をつけたloopってやつを呼び出して変数の内容を更新している。(cons c ls1)の結果がls1に、(read-char p)の結果がcに入るんだと思うw、そうなるもんだと覚えるべきか。とりあえず今のところはそうしとこう。
ファイル読み込み(一文字ずつ)をRubyでやるとこうなる
#!/usr/bin/ruby ls1 = [] # 配列の初期化 open("/home/hironemu/hello.txt") {|f| while(c = f.getc) # 一文字ずつ読み込み、cへ代入 ls1 << c.chr # getcはASCIIコードを返すのでchrメソッドで文字に変換、そしてls1へ追加していく end } puts ls1.join # joinで配列を連結して出力
実行結果
$ ./read.rb Hello world! Scheme is an elegant programming language
ちなみにファイルをクローズしてないのはopne関数の中でクローズの処理をやってくれてるから。openにコードブロック({|f|〜}<この部分)を渡してる時は、勝手にやってくれてるんですねー。便利。