Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 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 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2007-10-19


Paul Graham氏のユーティリティ その6

| 03:16 | Paul Graham氏のユーティリティ その6 - わだばLisperになる を含むブックマーク はてなブックマーク - Paul Graham氏のユーティリティ その6 - わだばLisperになる

PG氏のユーティリティを読んでみることの6回目。

引き続きファイルの読み書きユーティリティ編です。

Lisp utilities that were not included in On Lisp or ANSI Common Lisp

お題

make-sb

暗記で再現

(defun make-sb ()
  (make-array '(0) :element-type 'base-char :adjustable 'T 
	      :fill-pointer 0))

とりあえずできた。sbって何の略だろう。string bufferとかだろうか…。

これもファイルの順番とは前後しますが後にでてくるfile-contentsが依存している関係で先にこなしています。

元のコードは、:element-typeがstring-charになっていますが、ANSIだと、base-charみたいなので直しました。

CTLT1では、string-charだったようです。手元で試した限りでは、clispでは、互換性が確保されている為か現状でもstring-charで通りました。

動作としては、後で追加できる文字列を作成するためのもののようです。

お題

sb-append

暗記で再現

(defmacro sb-append (as c)
  `(vector-push-extend (the character ,c) (the string ,as)))

とりあえずできた。make-sbで作った伸長可能な文字列に文字を追加するもののようです。

(let ((s (make-sb)))
  (sb-append s #\f)
  (sb-append s #\o)
  (sb-append s #\o)
  s)
;=> "foo"

お題

file-contents

暗記で再現

(defun file-contents (path)
  (awhen (probe-file path)
    (with-infile str it
      (let ((sb (make-sb)))
	(do-chars c str
	  (sb-append sb c))
	sb))))

とりあえずできた。ファイルから一文字ずつ読み込み結果を文字列にして返すというもののようです。

;; 動作
(file-contents "/tmp/foo.txt")
=>"foo bar baz"

お題

file-to-stream

暗記で再現

(defun file-to-stream (path &optional (out *standard-output*))
  (awhen (probe-file path)
    (with-infile str it
      (do-chars c str
	(princ c out)))))

とりあえずできた。file-contentsと殆ど同じで、結果をprincしているところが違うのみです。

お題

read-rest

暗記で再現

(defun read-rest (str)
  (let ((x (read str nil eof)))
    (if (eql x eof)
	nil
	(cons x (read-rest str)))))

とりあえずできた。ファイル(ストリーム)の内容をreadで読み込んでリストにして返すというもののようです。

;; 動作
(with-input-from-string (s "foo bar baz")
  (read-rest s))
;=>(FOO BAR BAZ)

お題

file-rest

暗記で再現

(defun file-rest (path)
  (awhen (probe-file path)
    (with-open-file (str it :direction :input)
      (read-rest str))))

;; with-infileで
(defun file-rest (path)
  (awhen (probe-file path)
    (with-infile str it
     (read-rest str))))

とりあえずできた。上のread-restをファイル用途に限定したもののようです。何故かこれだけ、with-infileが使われていなかったりしますが何か深い理由があるのか、それともこっちの定義の方がwith-infileより古かったりするのか理由は謎です。

お題

suck-dry

暗記で再現

(defun suck-dry (str)
  (do ((c (read-char str nil :eof) (read-char str nil :eof)))
      ((eql c :eof) nil)))

;; 他とeofの判定方法を合わせた版
(defun suck-dry (str)
  (do ((c (read-char str nil eof) (read-char str nil eof)))
      ((eql c eof) nil)))

とりあえずできた。ファイルを読んで結果としてnilを返すというもの。

「吸い尽くす」ということですが、何に使うんでしょう。検証用とかでしょうか。

何故かこれだけ、EOFの検査にdefconstantで定義したeofを使っていなかったりします。

感想のようなもの

毎回(awhen (probe-file "foo") ~ it)するので、そこまで一つのマクロにしたらどうかしらとか思ったりしますが、うーん、どうなんでしょう。

(defmacro with-infile-if-probed (str path &body body)
  `(awhen (probe-file ,path)
     (with-infile ,str it ,@body)))

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20071019