「Ansi Common Lisp」7章読了
入出力に関する章。
普通のプログラミング言語の入門書なら、まず外せない内容でしょうね。
「ふつうのHaskellプログラミング」では、Wikiエンジンの開発の中で取り上げられていたみたいですが、ここ読んでないので結局標準入出力しか分かってないなあ。。
ストリーム
ファイルを書き込んでみる。
* (setf path (make-pathname :name "myfile")) Warning: Declaring PATH special. #p"myfile" * (setf str (open path :direction :output :if-exists :supersede)) #<Stream for file "myfile"> * (format str "Something~%") NIL * (close str) T *
taka@taka-desktop:~/lisp$ more myfile Something taka@taka-desktop:~/lisp$
ファイル名としていきなり文字列を与えるのではなく、パス名とかいうのを与えるらしい。原注に、
パス名の代わりにストリングを与えることもできるが、可搬性がない。
とあるので、一応やってみる。
* (setf str (open "myfile2" :direction :output)) #<Stream for file "myfile2"> * (format str "Hello, world!") NIL * (close str) T *
taka@taka-desktop:~/lisp$ more myfile2 Hello, world! taka@taka-desktop:~/lisp$
普通に動くみたい。
今度はファイルを読んでみる。
* (setf in (open "myfile2" :direction :input)) Warning: Declaring IN special. #<Stream for file "myfile2"> * (read-line in) "Hello, world!" T * (close in) T *
with-open-fileマクロを使うと、Rubyのブロック付きopenみたいなことが出来るらしい。(というか、Rubyのブロック付きopenが、Common Lispのwith-open-fileマクロみたいなもの。といった方がいいのかも。歴史的背景は良く分かりませんが。。)
つまり、読み込みとか書き込みに失敗しても、closeは保証されますよっていうことです。
* (with-open-file (str path :direction :output :if-exists :supersede) (format str "Anything~%")) NIL *
taka@taka-desktop:~/lisp$ more myfile Anything taka@taka-desktop:~/lisp$
入力
readは、入力を解析してLispオブジェクトとして返す。
* (setf abc (read)) Warning: Declaring ABC special. (lambda (x) (* x 2)) (LAMBDA (X) (* X 2)) * abc ; (LAMBDA (X) (* X 2)) * (eval abc) #<Interpreted Function (LAMBDA (X) (* X 2)) {580BF109}> * (funcall (eval abc) 2) ; 4 *
なんでevalしないと動かせないのだろうと思ったら、
* (inspect abc) Object is a LIST of length 3. 0. LAMBDA 1. (X) 2. (* X 2) >
単なるリストだからなのですね。
出力
出力といえばformat(printfみたいなもの)ばかり使ってきましたが、prin1、princ、printなどの関数も使えるようです。
* (prin1 "Hello") "Hello" "Hello" * (princ "Hello") Hello "Hello" * (print "Hello") "Hello" "Hello" *
マクロ文字
マクロ文字(macro character)は、readが特別扱いする文字である。
とあるように、リストを作るための"("や")"、quoteの省略形"'"、functionの省略形"#'"とか。