Clozure CL で load したファイルの返り値を受け取れるか
何らかの処理の書かれたファイルを読み込み、その返り値を受け取る、ということができないか試してみた。単純にloadしただけでは、ファイルのPATHが返されて期待した動作にならなかった。
? (defparameter x (load "/tmp/aaaa.lisp")) X ? x #P"/tmp/aaaa.lisp" ? (quit)
ちなみに中身は
(let ((a "100")) a))
となっていて、文字列の100が返されるようになっている。このファイルをwith-standard-io-syntaxで読み込みしても同じようにファイルのPATHが返される。
? (defparameter lll (with-standard-io-syntax (load "/tmp/aaaa.lisp"))) LLL ? lll #P"/tmp/aaaa.lisp" ?
ファイルそれ自体を読み込み、その読み込んだものをwith-standard-io-syntaxで処理したらどうなるか。
? (with-open-file (file "/tmp/aaaa.lisp" :direction :input) (with-standard-io-syntax (setf lll (read file)))) (LET ((A "100")) A) ? lll (LET ((A "100")) A) ?
これをfuncallしてみても関数形式じゃないと怒られる。
? (with-open-file (file "/tmp/aaaa.lisp" :direction :input) (with-standard-io-syntax (setf lll (read file)))) (LET ((A "100")) A) ? lll (LET ((A "100")) A) ? (funcall lll) > Error: (LET ((A "100")) A) is not of type (OR SYMBOL FUNCTION), and can't be FUNCALLed or APPLYed > While executing: FUNCALL, in process listener(1). > Type :POP to abort, :R for a list of available restarts. > Type :? for other options. 1 >
以下のようにラムダ式にすればfuncallできる。
? (funcall #'(lambda () (let ((a "100")) a))) "100" ?
そのため、もとのファイルを
(lambda () (let ((a "100")) a))
として、with-standard-io-syntaxで読み込んでみたが、これもダメ。
? (with-open-file (file "/tmp/aaaa.lisp" :direction :input) (with-standard-io-syntax (read file)))) (LAMBDA NIL (LET ((A "100")) A)) ? > Error: Reader error on #<CCL::RECORDING-CHARACTER-INPUT-STREAM #x302000FD419D>, near position 1: > Unmatched ')' . > While executing: CCL::SIGNAL-READER-ERROR, in process listener(1). > Type :POP to abort, :R for a list of available restarts. > Type :? for other options. 1 >
先頭に#'を付与して、funcallにいきなり渡すようにしてみたがそれもうまくいかない。
#'(lambda () (let ((a "100")) a))
? (funcall (with-open-file (file "/Users/shimpei/aaaa.lisp" :direction :input) (with-standard-io-syntax (read file))))) > Error: #'(LAMBDA NIL (LET ((A "100")) A)) is not of type (OR SYMBOL FUNCTION), and can't be FUNCALLed or APPLYed > While executing: FUNCALL, in process listener(1). > Type :POP to abort, :R for a list of available restarts. > Type :? for other options. 1 >
結局、うまくできたのはevalを使った場合だけだった。
? (with-open-file (f "/tmp/aaaa.lisp" :direction :input) (do ((s (read-line f nil 'eof) (read-line f nil 'eof))) ((eql s 'eof)) (format t "~A~%" s))) (let ((a "100")) a)) NIL ? (eval (with-open-file (file "/tmp/aaaa.lisp" :direction :input) (with-standard-io-syntax (read file)))) "100" ?
evalを使ってまではやりたくない。このアプローチは使えないな。