1 名前:デフォルトの名無しさん mailto:sage [2007/06/10(日) 21:41:07 ] lispを触ってみたい入門者のQ&A 初心者のQ&A 本スレでは恥ずかしくて聞けない人のQ&A 本スレは高度すぎて割り込めない人のQ&A linuxでなくてwindowsでやりたいんですが・・・Q&A lispを使用してC#やJAVAの代替にするための方法(おまけ) ま、ゆっくりたりましょう。 「いいものの本質は、いかなる時代においても変わらない」byパワーズ (list (url pc8.2ch.net/test/read.cgi/tech/1101386936/l50 :part 1) (url pc11.2ch.net/test/read.so/tech/1140012484/l50 :part 2))
196 名前:169 mailto:sage [2007/07/07(土) 23:29:11 ] >>170 , 172 返答どうもです。とりあえず、(asdf:oos 'asdf:load-op :htmlgen)もしくは(require :htmlgen) で、何やらいろいろ読み込んでいるメッセージがでます。そのあと、サンプルファイルtest.clをloadしたいのだけど、 失敗します。test.clはファイルの先頭行で (defpackage :user (:use :htmlgen))をしているのだけど、(load "test.cl")したときに、 ----ここから debugger invoked on a SB-KERNEL:SIMPLE-PACKAGE-ERROR: The name "HTMLGEN" does not designate any package. Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name): 0: [ABORT] Exit debugger, returning to top level. (SB-INT:%FIND-PACKAGE-OR-LOSE "HTMLGEN") ----ここまで というエラーがでます。"HTMLGEN"というパッケージは存在しないという 内容のように見えますが、これはつまり最初の読み込みがうまく行ってないということでしょうか?
197 名前:169 mailto:sage [2007/07/07(土) 23:30:13 ] >>196 の続き htmlgen.asdファイルは以下のようになってます。 ----ここから kengo@Somali:/usr/share/common-lisp/source/htmlgen$ view htmlgen.asd ;;; -*- mode: lisp -*- (defpackage #:htmlgen-system (:use #:cl #:asdf)) (in-package #:htmlgen-system) (defclass acl-file (cl-source-file) ()) (defmethod source-file-type ((c acl-file) (s module)) "cl") (defsystem htmlgen :author "John K. Foderaro" :licence "LLGPL" :default-component-class acl-file :components ((:file "htmlgen")) :depends-on (acl-compat) :perform (load-op :after (op htmlgen) (pushnew :htmlgen cl:*features*))) ----ここまで まずasdfについて勉強しないと駄目なのかな・・・さっぱりわからん。。
198 名前:デフォルトの名無しさん mailto:sage [2007/07/07(土) 23:38:24 ] >>194 > 引数が同じなら何度呼んでも結果が変わらないのが副作用のない関数だよ。 ちょっと語弊があるんじゃないか? 結果って書くと普通は戻り値と解釈されることが多いが、戻り値が一定でも 副作用のある関数を書くことはできる。 逆に現在時刻を返す関数等は副作用があるとは言わないと思うし。
199 名前:デフォルトの名無しさん mailto:sage [2007/07/07(土) 23:47:54 ] 横レスだけど、 >逆に現在時刻を返す関数等は副作用があるとは言わないと思うし。 全く同じ引数を渡したのに毎回異なる結果(現在時刻)を返すのであれば、 参照透明が崩されるので副作用があると思います。 現在時刻に合わせて変動する環境へのポインタみたいなのを引数に渡す 様になっていればその限りでは無いと思いますが。
200 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 00:36:21 ] >>196 ubuntuのだとhtmlgenのパッケージ宣言がnet.html.generatorになっていてtest.clと異なるからダメポみたいだね。 取り合えずこうやって呼び出しパッケージ変更すると先にはいけます (require :htmlgen) (defun simple-table-a () (with-open-file (p "test.html" :direction :output :if-exists :supersede) (net.html.generator:html-stream p ;;net.html.generator:パッケージを指定 (:html (:head (:title "Test Table")) (:body (:table (:tr (:td "0") (:td "0")) (:tr (:td "1") (:td "1")) (:tr (:td "2") (:td "4")) (:tr (:td "3") (:td "9")) (:tr (:td "4") (:td "16")) (:tr (:td "5") (:td "25")))))))) でもこれよりhtml-templateの方が使いやすい気がするんだけどそれじゃいやなのかな? #実はcgiでlisp使おうとしてるんで学習がてらです。 #ちっともlisp自体には詳しくないです。
201 名前:200 mailto:sage [2007/07/08(日) 00:37:43 ] うぐ、コードはtest.clの物です、インデントは脳内で補間してください
202 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 00:42:57 ] 副作用という単語の定義の問題だと思う。個人的には時間取得関数を「副作用がある」と言う のには抵抗を感じる。便宜的に「副作用がある」と宣言して、ある種の最適化を抑止しなければ ならないケース(言語)は多いと思うけど。 上記の乱数の例についても、もし予測不能な「真の乱数」(物理乱数)を返す関数だったらどう だろう、とか考えてしまった。(混乱させてしまったらごめんなさい)
203 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 01:07:57 ] >>202 (setf a (f x)) こう書いたときにaが常に一意に決まる関数は副作用が無い。 aの結果が変わることを無視すれば副作用は無いように 見えるかもしれないけど 副作用の無い関数を組み合せた結果 副作用のある関数が作りうるのは副作用が無いといえないのではないか? と、この観点では真の乱数は副作用があって、 疑似乱数で必ず種を受けとらないと動作しないものは副作用の無い関数として 扱ってよいと考える。 オプショナルで省略されたデフォルトグローバルな種を書き換えるかどうかは この場合あまり重要ではない。 参照透明性とか言っている人はこういう風に考えているんじゃないかなと思った。 違ったらスマヌ
204 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 01:10:26 ] >>196 > (defpackage :user (:use :htmlgen))をしているのだけど、(load "test.cl")したときに、 (defpackage :user (:use :cl :net.html.generator)) とすればいいよ。asd の定義は Makefile のプロジェクト名とターゲット指定相当なんで 実際の CL におけるパッケージ名とは別。パッケージ名は net.html.generator 。 というかそのパッケージにはドキュメントついてこないのか。ヒドいなぁ…
205 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 01:11:21 ] 思考実験をする前に、脳内定義を外界と摺り合わせしておくのも悪くない事だと思う サンプルとして、純粋関数型言語オタクの言う副作用はこんな感じ ttp://www.sampou.org/haskell/article/whyfp.html
206 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 01:54:47 ] wikipediaの副作用の項にある 1. 同じ条件を与えれば必ず同じ結果が得られる 2. 他のいかなる機能の結果にも影響を与えない が良く分からん。 1は当然として(パソコンの時間が狂ってたらアレだけれど)、 2はどういう意味なんだ? 上の例だと時間取得関数は、その戻り値(時間)を使用した 関数の結果には影響を与えるから副作用を持つ?
207 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 02:16:33 ] >>206 2. は(上記疑似乱数の例のように)その関数を呼び出すことによって、その後に呼び出す関数の 動作が変化しないという意味じゃないかな。例えば上の疑似乱数の例は呼び出すことによって乱数 の系列がずれてしまうので副作用がある。 (正直、君の言っている意味のほうが理解できない)
208 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 02:20:03 ] その関数呼び出しによってほかの場所に影響をあたえる、ってのが副作用じゃない? random を一回呼び出すと次の random 呼び出しに影響を与えるけど、 時刻取得関数を呼び出しても次の時刻取得関数には影響をあたえない。 戻り値は『ほかの場所』じゃないから気にしなくていいんじゃないかな。 って書いてたら >>206 に先を越された。
209 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 02:20:40 ] >>206 じゃなくて >>207
210 名前:デフォルトの名無しさん [2007/07/08(日) 02:28:09 ] >>206 ぶっちゃけ状態を扱う関数はみんな副作用がある関数と言える 1.が状態を取り出す 2.が状態を書き換える 副作用というと書き換えるほうをイメージしちゃって>>202 みたいに思っちゃう人が多い
211 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 02:31:14 ] >>199 全く同じ引数を渡した時に同じ結果を返す(いわゆる「純関数」である)というのは副作用とは別の概念じゃないかな。 例えばグローバル変数の値を返すという関数は「純関数」ではないが「副作用がある」とは一般には言わないと思う。 時間を返す関数もこれと同じだよね。 もちろん、副作用のある関数は(たとえ同じ引数に同じ結果を返しても)「純関数」とは呼ばないだろうけど。
212 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 02:33:05 ] >>210 ああ「取り出すほうも副作用と呼ぶ」のか。議論がかみ合わない理由がわかった。 日本語的には激しく抵抗があるが、そういう定義は一般的なの?
213 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 02:42:11 ] 関数型言語屋はそういう定義を使うことが多いね(偏見かな)
214 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 04:52:39 ] >>212 日本語的にとかいい出すなら、参照透明でないものを関数と呼ぶ方が抵抗あるだろ……。
215 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 05:51:37 ] Lispってこんなこともできねーの?
216 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 09:07:59 ] >>214 副作用って一般的にも使うし、そもそも「作用」の一般的な意味が | (1)他に力や影響を及ぼすこと。また、そのはたらき。 | 三省堂提供「大辞林 第二版」 だから、「取り出すほうも副作用と呼ぶ」なんて言うのは違和感が あるのはしょうがない。 対して、参照透明なんて普通の人はあまり使わんから、どんな定義 でも「はあそういう定義ね。」っで終わり。 専門用語と一般的に使われる言葉の意味が異なることは珍しくないよ。
217 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 09:33:01 ] いや、>>214 が問題にしてるのは「参照透明」じゃなくて「関数」の方だと思う。 普通は関数っていったら数学の関数を想像するだろ?
218 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 10:23:20 ] 参照透明の定義をよく知らない人にとっては、「参照透明でないものを関数と呼ぶな」 って言われたら、「ふ〜ん、そうなんだ。」って思うだけで別に違和感を感じる余地 はあまりない。 「普通は関数っていったら数学的な関数を想像するだろ」とか書いてるけど、関数と 言う言葉のイメージって結構ばらばらなのはこの板の連中なら知ってて当然だから、 このスレではそういう(=「参照透明でないものは〜」と言う) 定義なんだと理解でき るだろうと思う。
219 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 10:35:44 ] >>218 参照透明という言葉を知ってるかどうかは関係ない。 printfみたいなのを関数と呼ぶ時点で慣れない人(非プログラマとか)には違和感があるだろ。 「副作用」という言葉が慣れない人にとって違和感のある意味で使われているのも、 「関数」という言葉の場合と同じ構造だ、って主張だと思うが。
220 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 12:53:05 ] 副作用のあるものも含めて「関数」と呼ぶのはソフトウェア業界全体に普及している表現だが、 「副作用が無い」を「参照透明」の意味で使うのはそれほど一般的ではないと思う。
221 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 15:12:09 ] 副作用の有無と参照透明性の有無は別々の話。関係はあるけど。 俺は「副作用」が>>210 の意味で使われるのって普通じゃないと思うんだけど そういう意味で使われている文脈って例えばどういうの?
222 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 15:19:05 ] >>221 >>213
223 名前:デフォルトの名無しさん mailto:sage [2007/07/08(日) 15:58:07 ] gccのinfo、関数のattributeの説明から > `const' > Many functions do not examine any values except their arguments, > and have no effects except the return value. (中略) > > The attribute `const' is not implemented in GCC versions earlier > than 2.5. An alternative way to declare that a function has no > side effects, which works in the current version and in some (後略) この "a function has no side effects" が意味するものは当然これ。 > Many functions do not examine any values except their arguments, > and have no effects except the return value.
224 名前:169 mailto:sage [2007/07/08(日) 17:07:58 ] >>200 ,>>204 おーー。できました! どうもありがとうございます。 net.html.generatorというのは、htmlgen.clの先頭で defpackageしている名前のことですね。 html-templateっていうのもあるんですか。 何がメジャーとかぜんぜん知らないんで一番最初に見つけたhtmlgenで とりあえずやってみました。他にもlmlとか言う名前のhtmlテンプレートも あったような気がする。いろいろあってわからんです
225 名前:デフォルトの名無しさん mailto:sage [2007/07/09(月) 00:31:09 ] >>222 具体的に例えばどれ?
226 名前:デフォルトの名無しさん mailto:sage [2007/07/09(月) 00:40:56 ] ごめ223見てなかった。Thanks.
227 名前:デフォルトの名無しさん [2007/07/09(月) 21:24:17 ] CLISPでのデバッグ方法を解説している日本のサイトはないでしょうか?
228 名前:デフォルトの名無しさん mailto:sage [2007/07/09(月) 23:49:25 ] どんなバグなのかによるんじゃないかな。バグ入り関数の例とか示せる?
229 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 08:45:11 ] www.kmonos.net/wlog/61.html これの、Curry-Howard Isomorphismの項なんだけれど、 これをCLでやるにはどうすればいいんだろう。 (a かつ (aならばb)) ならば b が haskellで Prelude> :t ¥x -> (snd x) (fst x) ¥x -> (snd x) (fst x) :: (a, a -> t) -> t らしいんだが、CLならどう書けばよいのかHaskellに詳しくないからさっぱり。 そもそもHaskellの::に相当する構文が無いからCLには無理?
230 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 09:03:24 ] CL には直積型がないからね cons で代用するとこうかな (lambda (x) (funcall (cdr x) (car x)))
231 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 09:09:01 ] そのまま (defun hoge (x) (funcall (cdr x) (car x)) 普通にカーリー・ハワード対応で調べればいいのに。
232 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 09:16:29 ] >>230 (lambda (x) (funcall (cdr x) (car x))) が :t ¥x -> (snd x) (fst x) に対応しているのは分かるんだけれど、 このラムダ式が定義できる事が、証明した事になるのかな?
233 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 09:28:45 ] >>232 > このラムダ式が定義できる事が、証明した事になるのかな? 疑問点がいまいちわかんない。 直観主義命題論理の証明と Lisp の関数とが対応するかということなら、 少なくとも上に書いたような方法では対応させられないと思う。
234 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 09:34:14 ] いや、証明に対応する関数は書けるか。 関数を書いても対応する証明があるとは限らない。 例えばこういうのは、対応する証明が命題論理の範囲にはない。 (lambda (x) (funcall x x))
235 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 09:41:03 ] >>233 >直観主義命題論理の証明と Lisp の関数とが対応するかということなら、 >少なくとも上に書いたような方法では対応させられないと思う。 残念、無理なのか。 いや、カーリー・ハワード対応という言葉を今回初めて知って、 (Lispで数式証明のアプリケーションが有るのは知ってるけれど) んで、(a かつ (aならばb)) ならば bを証明してみたいなぁと思った訳です。
236 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 13:47:03 ] >>235 (lambda (x) (funcall (cdr x) (car x))) を満たすようなxの値が存在することが証明に対応、 つまりそんなxを一つ挙げればいい……んじゃなかったっけ? うろ憶え。
237 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 16:38:25 ] 静的な型がないと駄目だな。 \x -> x xはHaskellでは型エラー。
238 名前:デフォルトの名無しさん mailto:sage [2007/07/10(火) 22:14:43 ] (defun hoge (a b) (if (and a (eql a b)) b nil)) じゃ、ダメなのかな? っーかこの分野って、やってる人少ないのかな? あんまりレスないね。 ここの人、こんなこと好きそうなイメージなんだけれど。
239 名前:デフォルトの名無しさん mailto:sage [2007/07/11(水) 00:51:45 ] Cで書いたプログラムとCLispで書いたプログラムを 互いに通信させたいんだけど,そういった場合ってやっぱSocket? 何かいいライブラリとかありませんかね
240 名前:200 mailto:sage [2007/07/11(水) 01:40:07 ] 通信だとsocketですが、お互いのやり取りの中身が直接呼び出しだったり、共有メモリでなんとかできるのならCFFIあたりを使ってみてはどうですか? OpenGLの呼び出しとかで使われてるやつです。
241 名前:デフォルトの名無しさん mailto:sage [2007/07/11(水) 04:06:54 ] >>238 本スレ行ったほうがいいかもね。 その手の話はスキーマーのほうが乗ってくる。
242 名前:デフォルトの名無しさん mailto:sage [2007/07/11(水) 09:27:13 ] >>238 λ計算は知ってるけど、Lisp とはそれほどきれいに対応しないと思う。 ちなみにそのコードは Curry-Howard とはぜんぜん関係ないような。
243 名前:デフォルトの名無しさん mailto:sage [2007/07/13(金) 00:19:32 ] (format t "~X ~X~%" a b)とやって #(69) 69 と表示されるんですが,同じ数値でも片方に#()がついてしまいます. これってただの数値じゃないってことですか? その成果,後々にa = #x69とやってもTになってくれません aは (let ((a (make-array 1 :element-type '(unsigned-byte 8))))) とかやって EXT:READ-BYTE-SEQUENCEとかで読み込んだ値なんですが...
244 名前:デフォルトの名無しさん mailto:sage [2007/07/13(金) 00:24:36 ] >>243 ただの数値じゃないんですよ。配列ってわかります?
245 名前:デフォルトの名無しさん mailto:sage [2007/07/13(金) 00:27:13 ] >>244 それだ!
246 名前:デフォルトの名無しさん [2007/07/13(金) 21:41:29 ] Lispの練習問題を探していて Define show-list to act like Lisp's PRINT, except that it should print square brackets instead of parentheses. (Printing to a string and replacing parentheses doesn't count.) Both functions should be able to print any S-expression, including atoms. > (show-list '(a b c)) → [A B C] ってのを見つけました。 これを、"ANSI Common Lisp"の第3章までの知識で解きなさい、ってんですけ ど、オジサンの頭ではどーにもなりません。 そのものズバリでなくても、ヒントとか考え方とか教えていただけないでしょ うか?
247 名前:デフォルトの名無しさん mailto:sage [2007/07/13(金) 22:14:08 ] SBCLでcompile-fileしてもあんまり速くならないんですが、 何か他に速くする手段てあるでしょうか?
248 名前:デフォルトの名無しさん [2007/07/13(金) 22:39:40 ] >>246 1. 全てのS式を表示だからatomの場合、consの場合、nilの場合で場合わけすることになるはず。atomとnilは自明。 2. consの場合の表示を分解すると括弧の表示+最初の要素を表示(要素はさらにconsかもしれない)+残りの表示+括弧閉じになるはず。 3. この「残りの表示」を別関数で定義してみる。(←ここがポイント) 4.「残りの表示」の場合わけもさっきと同様になる。 5. ここでconsの場合の処理はやっぱり「最初の要素について(これもconsかもしれない)」「残りについて」になる。
249 名前:デフォルトの名無しさん mailto:sage [2007/07/13(金) 22:42:50 ] 説明下手糞?
250 名前:デフォルトの名無しさん [2007/07/13(金) 22:48:00 ] ごめん、代わりに頼むよ
251 名前:デフォルトの名無しさん [2007/07/14(土) 00:35:32 ] >>248 おぉ、早速ありがとうございます。 参考にしていろいろいじってみます。 日本語で読むと簡単そうに見えるんだけどなぁ。 (defun show-list (lst) (if (null lst) lst (if (atom lst) : って感じでいいんですよね?
252 名前:デフォルトの名無しさん mailto:sage [2007/07/14(土) 00:55:32 ] 配列とか構造体とか () 使うのはほかにもあるけど symbol と cons だけでいいのかな >>251 > (if (null lst) > lst "nil" って文字列を印字しなきゃいけないんでないの?
253 名前:246 mailto:sage [2007/07/14(土) 09:21:45 ] >>252 あぅ。やっちまった orz 自分で言っといて... (defun show-list (lst) (format t "~A" (rec-show-list lst))) (defun rec-show-list (lst) if (null lst) lst : なんてのを考え中。
254 名前:デフォルトの名無しさん mailto:sage [2007/07/14(土) 10:16:14 ] >>247 sbclはコンパイラのみの処理系だから、ソースをロードしても実行時には コンパイルされていると思う。だから差を感じられないということじゃないかな。
255 名前:デフォルトの名無しさん mailto:sage [2007/07/14(土) 13:51:28 ] >>253 その設計は無理があると思う だって format って () 使うじゃん
256 名前:デフォルトの名無しさん mailto:sage [2007/07/14(土) 17:59:26 ] >>246 問題が「show-listを作れ」ってなってるのがミスリーディングかも。 任意の式を出力する関数show-exprを作れ、が普通じゃなかろうか。 ただしリストの表示にはパーレンの代わりにブラケットを用いる。
257 名前:246 mailto:sage [2007/07/14(土) 19:44:08 ] なんか盛り上がってるし(^^;)。 >>255 > だって format って () 使うじゃん ごめんなさい。これ分かりません。 format使うと必ず()がつくってこと? >>256 "ANSI Common Lisp"の3章の練習問題なので、そこまでの知識で解かないとい けないのかな、と思ってます。 出力用の関数はformat、データ形式もリスト(とアトム)のことだけ考えればい いのかと。
258 名前:255 mailto:sage [2007/07/14(土) 20:17:05 ] >>257 たとえば (format t "~A" x) で [a b c] が出力されるような x ってどんなもの? ところでリストでもアトムでもないオブジェクトってあったっけ
259 名前:デフォルトの名無しさん mailto:sage [2007/07/14(土) 23:18:09 ] んん?問題は良い問題なのになんか根本的に間違った方向にいってないか? S-式は、リストと思わずに木(ツリー)と思った方がいい。 で、木の要素を順番に辿る。木の要素が atom か consp かで場合分け。 consp だったら、 まず [ を出力し、hogehoge の処理をして最後に ] を出力する。 任意の入れ子になった木を出力できないと行けないんだから、 hogehoge は言わなくても分かるな?
260 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 00:39:44 ] 要するにwrite相当を実装しろってことでしょ? (defun write-list(exp) (princ "[") (loop (if (not (consp exp)) (return)) (write (car exp)) (setq exp (cdr exp)) (if (consp exp) (princ " ") (if (not (null exp)) (progn (princ " . ") (write exp))))) (princ "]")) (write-list '(a b c . d)) [A B C . D] write本体は自分で考なよおじさん ちなみに俺もCommonLisp初めてなんだけど、 whileって無いみたいね。 上の(loop (if (not (consp exp)) (return)) 〜 ) てかなりマヌケな気がするんだけど、もっと簡単にできない? whileがあれば(while (consp exp) 〜)で済むのに
261 名前:デフォルトの名無しさん [2007/07/15(日) 00:40:40 ] doがあるよ
262 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 00:44:46 ] これでしょ? (defmacro while (condition &body body) `(do () ((not ,condition)) ,@body)) でもdoはなんとなくキモイんだよな…
263 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 01:57:06 ] ループの話題で思い出したけど、 最新版のSBCLで以下のコードがn=5000程度で死ぬんですが、 末尾再帰の最適化はしてくれないんでしょうか? (defun w(n) (labels ((x (n) (write n) (if (> n 0) (y (- n 1)) )) (y (n) (write n) (if (> n 0) (z (- n 1)) )) (z (n) (write n) (if (> n 0) (x (- n 1)) ))) (x n))) (w 5000) ;程度で死ぬ schemeでは (define (w n) (letrec ((x (lambda (n) (write n) (if (> n 0) (y (- n 1))))) (y (lambda (n) (write n) (if (> n 0) (z (- n 1))))) (z (lambda (n) (write n) (if (> n 0) (x (- n 1)))))) (x n))) (w 10000000000) ;nをいくら大きくしてもOK
264 名前:デフォルトの名無しさん [2007/07/15(日) 02:46:34 ] >>258 3 章までとか言われてもよくわかんないけど、princ くらいはあるのかな? 考え方: 0. リストがわたってくる 1. [ を表示 2. 各要素を表示 2-1. 要素がもうないなら終わり 2-2. 要素を一個表示して 2. へ 3. ] を表示 (defun show-list (lst) (princ "[") ; 1 (show-list-contents lst) ; 2 (princ "]")) ; 3 (defun show-list-contents (lst) (cond ((null lst) ; 2-1 nil) (t ; 2-2 (princ (car lst)) (show-list-contents (cdr lst)))))
265 名前:264 mailto:sage [2007/07/15(日) 02:48:28 ] 264 のリスト内のリストも [] で表示するのは課題としときます。 ヒント: 要素がリストなのかアトムなのかを判定して… >>260 while の内部実装が do でキモいというなら↓でどうでしょう。 (loop while (consp exp) do ....) これも嫌なら素直に Scheme を使ったほうがいいと思います。 >>263 SBCL 1.0.7 で disassemble して末尾再帰の最適化もされている事を確認しました。 (w 10000000000) も普通に動いてるようですが。
266 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 03:24:34 ] >>263 ごめんWindows版だから1.0.6だった。 普通にインストーラで作成されるショートカットから起動して >>263 のコードをコピペ。 (w 10000)で 12840283928fatal error encountered in SBCL pid 2812: GC invariant lost, file "gencgc.c", line 832 LDB monitor ldb> となって止まる。 今確認したら5000だとなんか完了したりもするので10000で。 6000辺りだとプロンプト'*'が連続表示して暴走した風になって、 タスクマネージャで見るとメモリをどんどん消費していくのが判る。 ほっとくとOS側(XP Pro. SP2)でメモリ不足のダイアログが出る。 Windows版特有なのかな・・?
267 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 03:25:23 ] ごめん上は>>265 宛て
268 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 03:28:54 ] * (disassemble 'w)してみたけど、最適化掛かってるかわからないので よければ鑑定お願いします。 ; 0A626C8E: 8B45F0 MOV EAX, [EBP-16] ; no-arg-parsing e ntry point ; C91: 8945F4 MOV [EBP-12], EAX ; C94: E9FB000000 JMP L14 ; C99: L0: 8BDC MOV EBX, ESP ; C9B: 83EC0C SUB ESP, 12 ; C9E: 8B55F4 MOV EDX, [EBP-12] ; CA1: 8B05586C620A MOV EAX, [#xA626C58] ; #<FDEFINITION object for WRITE> ; CA7: B904000000 MOV ECX, 4 ; CAC: 896BFC MOV [EBX-4], EBP ; CAF: 8BEB MOV EBP, EBX ; CB1: FF5005 CALL DWORD PTR [EAX+5] ; CB4: 7302 JNB L1 ; CB6: 8BE3 MOV ESP, EBX ; CB8: L1: 8B55F4 MOV EDX, [EBP-12] ; CBB: 31FF XOR EDI, EDI ; CBD: E84E979DF7 CALL #x2000410 ; GENERIC->
269 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 03:29:59 ] ; CC2: 7302 JNB L2 ; CC4: 8BE3 MOV ESP, EBX ; CC6: L2: 81FA0B001002 CMP EDX, 34603019 ; CCC: 750F JNE L4 ; CCE: BA0B001002 MOV EDX, 34603019 ; CD3: L3: 8D65F8 LEA ESP, [EBP-8] ; CD6: F8 CLC ; CD7: 8B6DFC MOV EBP, [EBP-4] ; CDA: C20400 RET 4 ; CDD: L4: 8B55F4 MOV EDX, [EBP-12] ; CE0: BF04000000 MOV EDI, 4 ; CE5: E848959DF7 CALL #x2000232 ; GENERIC-- ; CEA: 7302 JNB L5 ; CEC: 8BE3 MOV ESP, EBX ; CEE: L5: 8955F4 MOV [EBP-12], EDX ; CF1: 8BDC MOV EBX, ESP ; CF3: 83EC0C SUB ESP, 12 ; CF6: 8B55F4 MOV EDX, [EBP-12] ; CF9: 8B05586C620A MOV EAX, [#xA626C58] ; #<FDEFINITION object for WRITE> ; CFF: B904000000 MOV ECX, 4 ; D04: 896BFC MOV [EBX-4], EBP ; D07: 8BEB MOV EBP, EBX ; D09: FF5005 CALL DWORD PTR [EAX+5]
270 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 03:31:13 ] ; D0C: 7302 JNB L6 ; D0E: 8BE3 MOV ESP, EBX ; D10: L6: 8B55F4 MOV EDX, [EBP-12] ; D13: 31FF XOR EDI, EDI ; D15: E8F6969DF7 CALL #x2000410 ; GENERIC-> ; D1A: 7302 JNB L7 ; D1C: 8BE3 MOV ESP, EBX ; D1E: L7: 81FA0B001002 CMP EDX, 34603019 ; D24: 7507 JNE L8 ; D26: BA0B001002 MOV EDX, 34603019 ; D2B: EBA6 JMP L3 ; D2D: L8: 8B55F4 MOV EDX, [EBP-12] ; D30: BF04000000 MOV EDI, 4 ; D35: E8F8949DF7 CALL #x2000232 ; GENERIC-- ; D3A: 7302 JNB L9 ; D3C: 8BE3 MOV ESP, EBX ; D3E: L9: 8955F4 MOV [EBP-12], EDX ; D41: 8BDC MOV EBX, ESP ; D43: 83EC0C SUB ESP, 12 ; D46: 8B55F4 MOV EDX, [EBP-12] ; D49: 8B05586C620A MOV EAX, [#xA626C58] ; #<FDEFINITION object for WRITE> ; D4F: B904000000 MOV ECX, 4 ; D54: 896BFC MOV [EBX-4], EBP ; D57: 8BEB MOV EBP, EBX ; D59: FF5005 CALL DWORD PTR [EAX+5]
271 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 03:32:07 ] ; D5C: 7302 JNB L10 ; D5E: 8BE3 MOV ESP, EBX ; D60: L10: 8B55F4 MOV EDX, [EBP-12] ; D63: 31FF XOR EDI, EDI ; D65: E8A6969DF7 CALL #x2000410 ; GENERIC-> ; D6A: 7302 JNB L11 ; D6C: 8BE3 MOV ESP, EBX ; D6E: L11: 81FA0B001002 CMP EDX, 34603019 ; D74: 750A JNE L12 ; D76: BA0B001002 MOV EDX, 34603019 ; D7B: E953FFFFFF JMP L3 ; D80: L12: 8B55F4 MOV EDX, [EBP-12] ; D83: BF04000000 MOV EDI, 4 ; D88: E8A5949DF7 CALL #x2000232 ; GENERIC-- ; D8D: 7302 JNB L13 ; D8F: 8BE3 MOV ESP, EBX ; D91: L13: 8955F4 MOV [EBP-12], EDX ; D94: L14: E900FFFFFF JMP L0 ; D99: 90 NOP ; D9A: 90 NOP ; D9B: 90 NOP ; D9C: 90 NOP ; D9D: 90 NOP ; D9E: 90 NOP ; D9F: 90 NOP ; DA0: CC0A BREAK 10 ; error trap ; DA2: 02 BYTE #X02 ; DA3: 18 BYTE #X18 ; INVALID-ARG-COUNT-ERROR ; DA4: 4D BYTE #X4D ; ECX ; NIL
272 名前:265 mailto:sage [2007/07/15(日) 04:08:49 ] >>266 あーそゆことか。コードはちゃんと最適化されてるが GC 回りのバグですね。 SBCL の Windows 版はまだ試験的なものなんで安定してないんだよ。 Windows な開発者も少ないしね。ごめんね SBCL にかわってごめんね
273 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 04:44:16 ] うーむ、GC周りのバグってことは、ちゃんとプロテクトされてない ってことかな?結構いい加減ですね・・。 ちなみにclisp(clisp-2.41-win32-mingw-without-readline.zip)で 同じ様にcompileして実行しても、 *** - Program stack overflow. RESET と出るんですけど、こっちは何とかなりませんかね。
274 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 08:15:12 ] 俺も初心者ですが、こんなので合ってますか。 (defun show-list (lst) (cond ((atom lst) (format t "~A" lst)) (t (format t "[") (show-list (car lst)) (show-rest (cdr lst))))) (defun show-rest (lst) (cond ((null lst) (format t "]")) ((atom lst) (format t " . ~A]" lst)) (t (format t " ") (show-list (car lst)) (show-rest (cdr lst)))))
275 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 12:19:07 ] >>273 clisp について、(declare (optimize (speed 3))) とかしたらどうでしょうか。 www.lispworks.com/documentation/HyperSpec/Body/d_optimi.htm 今手元に環境がないんでちょっとあれでなにですが。
276 名前:265 mailto:sage [2007/07/15(日) 13:03:18 ] >>273 うーむ、experimental と明示されてる Windows 版をつかって、そゆこというのは 味付け前の料理をつまみ食いして「味が薄い!!」とシェフにクレームつけるようなもんだよ。 安定してる Linux/BSD プラットフォームでは動いてるし。原因も、そのメッセージだけじゃ GC そのものかコンパイラの出力かは情報不足だしね。 >>275 ちょっとソースみてみたけど、CLISP のオプティマイザはそのケースを最適化しない。 選択肢としては商用のコンパイラを使うとか、スタイルを換えるとか…まぁ、素直に Scheme 使うといいと思います。
277 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 13:42:14 ] >>275 (defun w(n) (declare (optimize (speed 3))) (labels ((x (n) (write n) (if (> n 0) (y (- n 1)) )) (y (n) (write n) (if (> n 0) (z (- n 1)) )) (z (n) (write n) (if (> n 0) (x (- n 1)) ))) (x n))) としても *** - Program stack overflow. RESET は変わりませんでした。((optimize (space 3))等も試しました。) (compile 'w)や、(compile-file "w.lisp")(load "w.fas")も同じ。 ソース中やdoc\impnotes.htmlにdeclare 〜 speed が見つからなかったので、対応してないのかな。 ちなみに sbcl-1.0.7/src/runtime/gencgc.c:832 を見ると gc_assert(alloc_region->start_addr == (page_address(first_page) + page_table[first_page].bytes_used)); で停止。ちょっと見ただけでは修正は無理そうです。 そもそも10000程度のループでgcが必要になるってのが、 よくわからない。本当に最適化が効いてるのか怪しいです。 例えば自作のscheme処理系では360セル程しか消費してないです。 その内 式'(w 10000)のコンパイル時に必要になるのがほとんどで、 式そのものを実行する準備に6セル、(w 10000)実行中は消費量ゼロです。
278 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 14:25:37 ] よくわからない→これま末尾再帰の最適化が効いていないに違いない、ね… SBCL 使ったことねーけど cons セルの消費は write のI/O 周りとか boxing だろ? 正直、末尾再帰に納得しても #' とか健全マクロとかで「〜は○○できないんですか?僕の自作 Scheme なら…」 とか無限ループになりそうなのであなたは Scheme 使っていたほうがいいと思います。
279 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 14:55:31 ] (defun x (n) (write n) (if (> n 0) (y (- n 1)) )) (defun y (n) (write n) (if (> n 0) (z (- n 1)) )) (defun z (n) (write n) (if (> n 0) (x (- n 1)) )) (x 10000) (defun w(n) (labels ((x (n) (write n) (if (> n 0) (x (- n 1)) ))) (x n))) (x 10000) (defun x(n) (write n) (if (> n 0) (x (- n 1)) )) (x 10000) どのパターンもおかしくなるみたいです。 というか今更気付いたんですが、 (gc)を単体実行しただけで戻ってこない場合がありました。 これはちょっと使えるというレベルではありませんね・・。 >>276 すいません。Winで使うことしか頭になかったので。 仕事で使えるかなと淡い期待を持ってたんですが、、 速さこそ正義なCLの思想は好きなんですが、 今までどうにも環境に恵まれないです。 cmuclが動く*NIXな仕事に着きたいなあ・・
280 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 15:23:56 ] >>278 そうですね。確認したらwriteが馬鹿食いしてるみたいです。 nがfixnum範囲ならばOKな様です。 今回は代表的なCL処理系でも末尾再帰スタイルが 実用上無理な物があると確認できただけでも収穫でした。 まあ心配されなくともschemeに戻るでしょう。
281 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 16:00:04 ] すげぇ結論だな。ふつうは開発中のものは実用に耐えないっすね、となりそうなもんだが。まぁ煽りたかっただけなんだろなぁ…
282 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 16:04:13 ] 結論ありきですから
283 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 16:57:09 ] >>281 clispのことでは 事実をただの煽りとして受け取った時点で これ以上何も言うつもりはないけどさ
284 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 16:59:07 ] lisp脳の他にschemerには再帰脳の恐怖もあるよな…
285 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 17:02:28 ] やっぱloopの話題になると荒れるね
286 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 17:19:40 ] 主要な処理系てclisp のことなのかよ。じゃあ sbcI については誤解はとけたのね。商用も大丈夫だし、わさわざ出来ない環境さがしてんのかとオモタョ ゴメンネ
287 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 18:58:55 ] scheme最強
288 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 19:00:19 ] >>287 氏ね
289 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 21:06:04 ] いい加減にSchemeはゴミだって認めようよ。
290 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 21:36:36 ] CLerから出てくる語彙が精一杯考えて氏ねとかゴミなのはよくわかったよ
291 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 21:38:55 ] スルー推奨
292 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 23:28:14 ] Schemeは子供用のおもちゃみたいなもの
293 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 23:30:13 ] >>290 巣へお帰りください pc11.2ch.net/test/read.cgi/tech/1177065699/
294 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 23:40:38 ] RHELユーザが 「plan9はアプリが少ない」 って言ってるようなもの
295 名前:デフォルトの名無しさん [2007/07/16(月) 21:01:29 ] 質問です。 2つのリストを、それぞれシンボルの集合とみなして、 左のリストと右のリストが一致するかどうかを判定し、 一致するなら右のリスト中のシンボルのそれぞれの 左に対応する位置インデックスを得たいのですが、 一個一個線形探索するより効率の良い方法はあるでしょうか? (set-compare-pos '(a b c) '(b c a)) =>(0 2 1) ; 一致したのでそれぞれの位置インデックスを返す (set-compare-pos '(a b c) '(b c a d)) =>nil ; 一致しない
296 名前:デフォルトの名無しさん [2007/07/16(月) 21:07:04 ] ごめんなさい間違えました。 (set-compare-pos '(a b c) '(b c a)) =>(2 0 1) ; 一致したのでそれぞれの位置インデックスを返す 。 これの意味は、 左の集合のaは、右の集合の2番目にある 左の集合のbは、右の集合の0番目にある 左の集合のcは、右の集合の1番目にある です。