[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 901- 2chのread.cgiへ]
Update time : 03/26 12:58 / Filesize : 286 KB / Number-of Response : 995
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

CommonLisp Scheme Part11



1 名前:デフォルトの名無しさん mailto:sage [04/08/02 23:13]
過去スレ
Part1: piza2.2ch.net/tech/kako/987/987169286.html
Part2: pc.2ch.net/tech/kako/1002/10025/1002584344.html
Part3: pc.2ch.net/tech/kako/1008/10082/1008220265.html
Part4: pc.2ch.net/tech/kako/1016/10162/1016211619.html
Part5: pc3.2ch.net/tech/kako/1023/10230/1023091882.html
Part6: pc3.2ch.net/tech/kako/1031/10315/1031560687.html
Part7: ruku.qp.tc/dat2ch/0311/20/1042167213.html
Part8: pc2.2ch.net/tech/kako/1058/10582/1058263391.html
Part9: pc2.2ch.net/test/read.cgi/tech/1069594582/
Part10: pc5.2ch.net/test/read.cgi/tech/1075630259/

関連リンクは>>2-10あたり


267 名前:デフォルトの名無しさん mailto:sage [04/09/12 00:16:38]
>>258 266
とりあえず、次ので日本語できたっぽい。
Mac OS X, OpenMCL でだけど
diff -r1.397 slime.el
1430c1430
< (set-buffer-multibyte nil))
---
> (set-buffer-multibyte t))
1439c1439,1440
< (let* ((msg (concat (slime-prin1-to-string sexp) "\n"))
---
> (let* ((msg0 (concat (slime-prin1-to-string sexp) "\n"))
> (msg (encode-coding-string msg0 'euc-jp-unix))
1442c1443
< (process-send-string proc (string-make-unibyte string))))
---
> (process-send-string proc string)))
1502c1503,1504
< (let ((string (buffer-substring start end)))
---
> (let* ((string0 (buffer-substring start end))
> (string (decode-coding-string string0 'euc-jp-unix)))


268 名前:デフォルトの名無しさん mailto:sage [04/09/12 01:00:18]
うおおお
sortがでけた

269 名前:デフォルトの名無しさん mailto:sage [04/09/12 16:27:08]
Corman Lispの作者のCormanさんから宣伝メールが来たよ。
Lispの処理系売って食ってくというのは苦労してるんかね。
とにもかくにも日本語がちゃんと扱えないことにはねえ。


270 名前:デフォルトの名無しさん mailto:sage [04/09/13 16:15:43]
前から思っていたんだけれど、
スペシャルフォームをファーストクラス・オブジェクトにすることはできない
だろうか?
スペシャルフォームを引数にとったり、関数の戻り値としたりできないだろうか?

> or
<#special form>  <-- 通常なら syntax error
> (or #f 3)
3

こんな感じで、スペシャルフォームが単独で入力されても文法エラーに
ならないようにすれば、うまく行くような気がするのだけど、どうでしょう?

271 名前:デフォルトの名無しさん mailto:sage [04/09/13 16:32:46]
>>270
Gaucheだとできてしまう。

gosh> set!
#<syntax set!>
gosh> define
#<syntax define>
gosh> (define hoge #f)
hoge
gosh> (set! hoge define)
#<syntax define>
gosh> (hoge x 1)
x
gosh> x
1


272 名前:270 mailto:sage [04/09/13 16:37:59]
ええー!Gauche って便利なのね。すごーい!

と言うか、なんで PetiteChezScheme だとできないのだろう??
何か不都合があるのでしょうか?
使えるほうが、絶対便利だと思うのだけど。

273 名前:270 mailto:sage [04/09/13 16:55:53]
すると Gauche では、こんなこともできちゃうのでしょうか?

gosh> ((lambda (x y) (x #f y)) or 3)
3

スペシャルフォームは、car の位置にきたときだけ機能するようにすれば
こういう書き方も ok だと思うのだけど。

274 名前:デフォルトの名無しさん mailto:sage [04/09/13 16:56:18]
もはやGaucheは、かつてgccがCじゃなかったくらいにschemeじゃない気がする。
gccの場合はしばらくしたら標準が追い付いてきたので、
schemeもあと十年くらい待てば>>270みたいのが標準で使えるようになるかもよ。


275 名前:デフォルトの名無しさん mailto:sage [04/09/13 17:01:39]
>>273
やってみた。

gosh> ((lambda (x y) (x #f y)) or 3)
*** ERROR: invalid application: (#<syntax or> #f 3)
Stack Trace:
_______________________________________
gosh> (let ((hoge or)) hoge)
#<syntax or>
gosh> (let ((hoge or)) (hoge #f 3))
*** ERROR: invalid application: (#<syntax or> #f 3)
Stack Trace:
_______________________________________

意外とよわよわだったな、Gauche……。




276 名前:270 mailto:sage [04/09/13 17:17:52]
>>275
あれれ、残念。
shiro さん、もし見てたら、ご検討お願いします。

277 名前:デフォルトの名無しさん mailto:sage [04/09/13 17:18:15]
guile> ((lambda (x y) (x #f y)) or 3)
3

できました

278 名前:270 mailto:sage [04/09/13 17:20:20]
>>277
おお!さすが何でもありの Guile!

279 名前:デフォルトの名無しさん mailto:sage [04/09/13 19:01:09]
それにしても、こんなに便利そうなのに、どうして標準になっていないのだろう?
何か問題があるのだろうか?

280 名前:デフォルトの名無しさん mailto:sage [04/09/13 19:59:08]
そりゃSchemeが便利ならなんでもありとは対極にあるような言語だからだろ


281 名前:デフォルトの名無しさん mailto:sage [04/09/13 20:17:07]
マクロの展開についての根深い対立が…。

282 名前:デフォルトの名無しさん mailto:sage [04/09/13 20:32:55]
夢の中で問題点を一つ思い付いた。関数はまず全部の引数を評価してしまうが、
syntaxはそうではない。わかりやすいところではand, or, begin, ifなど。

(define foo #f)
(or #t (begin (set! foo 3) foo))
とこれ↓を比べてね:
((lambda (x y) (x #t (begin (set! foo y) y))) or 3)

そう考えるとトップレベルでのみ別の名前に束縛できるというのは
それなりに意味があるかも。
しかしguileだと後者も難なくこなしてしまうようだ。どうなっとるんだ。

guile> (define foo 1)
guile> ((lambda (x y) (x #t (begin (set! foo y) y))) or 3)
#t
guile> foo
1
guile> ((lambda (x y) (x #t (begin (set! foo y) y))) and 3)
3
guile> foo
3

きっと、こんなことやってるからguileは遅いんだな……。


283 名前:デフォルトの名無しさん mailto:sage [04/09/13 20:34:59]
>>279
(or a b) はaがtrueならbが評価されないってところが大事なところでしょ。
手続きとして使いたければormapとかanyとかあるわけだし、自分でも作れる
わけだし。
構文は、実行前に意味が確定できることが肝なんであって、>>277みたいのを
標準にする意義がわからん。




284 名前:270 mailto:sage [04/09/13 20:45:37]
>>282
すばらしい!Guile のその挙動こそ、私が望んでいたものです。

>>283
それが、『Scheme手習い』の「lambdaは最高だ」に、スペシャルフォームを引数に
取れたら非常にシンプルに書けるような例が出ていたのです。
(実際はできないから、本では相互再帰を行って何とか解決していた)

285 名前:270 mailto:sage [04/09/13 20:48:12]
>>282
Guile の実装はぜんぜん知りませんが、
きっとスペシャルフォームを実行するのは car の位置に来たときだけ、という
ルールでやっているのじゃないかなあ。

そんなに速度も落ちないのじゃないかと思うのだけど。



286 名前:デフォルトの名無しさん mailto:sage [04/09/13 21:36:01]
実行時に展開と評価時に展開じゃ速度にかなり違いが出るような気が。

287 名前:デフォルトの名無しさん mailto:sage [04/09/13 21:41:43]
"special formを実行する" のは構文を parseするときではないのか?

>>277みたいなのは parseするときに決まってないんだからだめじゃん。

Haskellの世界にでもくれば shortcutなんかわざわざ意識しないでいいよ :-)


288 名前:270 mailto:sage [04/09/13 22:02:21]
うー、そういう問題があるのですか…。

スペシャルフォームを引数に取れると便利だという例をちょっと
書いてみました。
関数と違い、すべての要素を評価しないスペシャルフォームなので、
途中で結果がわかれば、リストを最後まで評価せずに止まります。

テストはしておりませんので、バグっていたらごめんなさい。

;関数を返す関数。引数に and か or を取る。
(define make-function
 (lambda (s-form)
  (lambda (list0)
   (s-form (atom? (car list0))
       ((make-function s-form) (cdr list0))))))

;リストにアトムが含まれるか?
(define has-atom? (make-function or))

;リストの要素がすべてアトムか?
(define all-atom? (make-function and))


289 名前:270 mailto:sage [04/09/13 22:03:35]
もしかして、Haskell のように遅延評価がデフォルトだと、
スペシャルフォームのほとんどは不要になるのでしょうか?

290 名前:デフォルトの名無しさん mailto:sage [04/09/13 22:14:28]
>>274
標準 (R5RS) では未定義あるいは実装依存とされている領域を利用しているだけだから
scheme ⊃ Gauche だよ

291 名前:デフォルトの名無しさん mailto:sage [04/09/13 23:13:29]
ふと気づいたのだけど、マクロもスペシャルフォームの一種だよね?
Guile って、マクロも実行時に展開しているんだろうか?
だとしたら、遅いのも道理だなあ…。

どなたかGuileユーザの方、確かめていただけませんか?

292 名前:デフォルトの名無しさん mailto:sage [04/09/13 23:34:50]
guile> (define-syntax my-or
    (syntax-rules ()
     ((_ x y) (or x y))))

guile> ((lambda (s-form y) (s-form #t (display y))) my-or 3)

これを試していただけませんか?
#t が返ってくるなら、マクロを実行時に展開していると思う。


293 名前:デフォルトの名無しさん mailto:sage [04/09/14 00:00:24]
>>292
Unbound variable: define-syntax
とか怒られた。

294 名前:デフォルトの名無しさん mailto:sage [04/09/14 00:06:55]
あれ?当然エラーは 2つ目の式で出たんですよね?
1つ目のdefine-syntax の式の実行で出たのではないですよね?

するとやはり Guile は他と同じで、パース時にマクロを展開するのかな?

295 名前:293 mailto:sage [04/09/14 00:14:21]
>>294
ごめん。(use-syntax (ice-9 syncase))忘れてた。
2つめの式で
ERROR: invalid syntax my-or
って出た。



296 名前:デフォルトの名無しさん mailto:sage [04/09/14 01:24:16]
了解。いずれにせよ、マクロ展開は実行時ではなく、解釈時なのね。
どうもありがとう。

そうしてみると、first class objectとして扱える special form はGuile の
場合、システム組み込みのものだけなのか。
ユーザ定義のマクロと、システム組み込みの special form を区別せずに扱えるのが
Lisp の良さの一つなのに、これでは価値半減だなあ。
実行してみるまで区別がつかないから、わかりにくいバグの元にもなりそうだ。

これなら、special form に別名を付けることしかできない Gauche の方が現実的な
落としどころのような気がする。

special form を first class として扱うためには、マクロ展開を実行時に行っても
構わないような、マシンパワーのあまりある時代を待つしかないのかもしれない。

297 名前:デフォルトの名無しさん mailto:sage [04/09/14 01:28:42]
まてよ。Gauche でも、マクロには別名は付けられないよね?
(define new-or my-or) は syntax error になると思う。

すると、ChezScheme のように、special form を一切拡張しないのが一番
現実的なのだろうか。何か寂しいなあ。

298 名前:デフォルトの名無しさん mailto:sage [04/09/14 01:39:04]
Gaucheではできる。Gaucheでは、コンパイル時に(手続き呼び出しではなく)
マクロだとわかるものならマクロ展開をしてくれるし、マクロの名前は
マクロそのものを返す。(define new-or my-or)も可能。

syntax classをapplicable objectにして、実行時に展開したら
おもしろいかも。evalが必要になるし、トップレベル以外の環境は
取得できないから無理だろうけどさ。

299 名前:デフォルトの名無しさん mailto:sage [04/09/14 05:00:28]
>>270
そういうのはマクロでやる。
実際、make-functionのコンパイル時にはs-formが構文かどうかは
わからないわけだから、コンパイラは ((make-function s-form) (cdr list0))
を評価してからs-formを呼ぶってコードを出すしかないじゃん。

>>287
Lazyなセマンティクスなら評価順の問題は出ないけど、「構文を
パラメタライズする」っていうのはもっと広い問題を含んでる。
Haskellでも、構文要素である '\' や '=' を関数引数として
渡すわけにはいかない。
構文のパラメタライズってのはメタプログラミングしてることになる。
Lispではマクロがメタプログラミングの道具。



300 名前:270 mailto:sage [04/09/14 10:38:48]
>>298
やっぱり Gauche はバランスがよく取れているということなのでしょうか。


>>299
そうか!マクロか!と思って、さっそく>>288 のコードをマクロ化してみました。

;元の関数
;(案の定バグがあった(停止しない)ので修正してある。)
(define make-function
 (lambda (s-form null-value)
  (lambda (list0)
   (if (null? list0)
     null-value
     (s-form (atom? (car list0)
         ((make-function s-form null-value) (cdr list0))))))))

;マクロ化したもの
(define-syntax make-function
 (syntax-rules ()
  ((_ s-form null-value)
   (lambda (list0)
    (if (null? list0)
      null-value
      (s-form (atom? (car list0))
          ((make-function s-form null-value) (cdr list0))))))))

そうしたら、マクロ展開が停止しないんです。再帰的定義なのに停止条件がないから。
この場合、どう書いたらよいのでしょうか?ヘタレですみません。

301 名前:270 mailto:sage [04/09/14 13:12:00]
『On Lisp』邦訳 10 マクロのその他の落し穴 10.4 再帰(P81)を読んでみました。
思ったより、解決は難しそうです…。

302 名前:デフォルトの名無しさん mailto:sage [04/09/14 15:30:55]
>>300
> やっぱり Gauche はバランスがよく取れているということなのでしょうか。

つーより、事前にコンパイルするんじゃguileみたいな挙動は不可能じゃね?
S式をそのまま解釈実行するのでないと。当然その場合実行速度は遅くなる。


303 名前:デフォルトの名無しさん mailto:sage [04/09/14 15:58:30]
なんか似たような話を見たことあるなあ……と思ってたんですが、
これなんか参考になりませんか? Common Lisp だけど。

ttp://home.comcast.net/~bc19191/blog/040527.html

304 名前:デフォルトの名無しさん mailto:sage [04/09/14 16:14:46]
>>270
実行時の停止条件と展開時の停止条件をごっちゃにしてると思われ。
停止を実行時に判断するなら、ループは実行時手続き呼び出しになる。

(define-syntax make-function
(syntax-rules ()
((_ s-form null-value)
(rec (f list0)
(if (null? list0)
null-value
(s-form (atom? (car list0))
(f (cdr list0))))))))

recはsrfi-31ね。letrecを使ってもよい。

停止を展開時に判断する場合は、実行しないでも停止条件がわかる
ことが必須。たとえば引数がリテラルリストで与えられているとか。
その場合はsyntax-rulesで再帰を書けばいい。

(syntax-rules ()
((_ s-form null-value val0)
(s-form (atom? val0) null-value))
((_ s-form null-value val0 val1 val2 ...)
(s-form (atom? val0)
(make-function null-value val1 val2 ...))))







305 名前:270 mailto:sage [04/09/14 22:43:09]
ありがとうございました。言われてみれば『On Lisp』そのままの話でしたが、
具体的に書いていただくまで分かりませんでした。お恥ずかしい。

rec という構文は初めて知りました。
ChezScheme ではそのままでは動かなかったので、少し変えました。

;; rec 版
(define-syntax make-function
 (syntax-rules ()
  ((_ s-form null-value)
   (rec f
    (lambda (list0)
     (if (null? list0)
       null-value
       (s-form (atom? (car list0))
        (f (cdr list0)))))))))

;; 名前つきlet (letrec)版
(define-syntax make-function
 (syntax-rules ()
  ((_ s-form null-value)
   (lambda (list0)
    (let loop ((list0 list0))
     (if (null? list0)
       null-value
       (s-form (atom? (car list0))
        (loop (cdr list0)))))))))

(define has-atom? (make-function or #f))

(define all-atom? (make-function and #t))



306 名前:270 mailto:sage [04/09/14 23:26:58]
今回は本当に勉強になりました。
今まで、special form が first class でない理由がずっとわからなかったの
ですが、答えはこうだったのですね。「マクロがあるから」

first class というのは関数抽象に関する概念で、special form は構文であるから、
そこには収まらない。それを扱うのは構文抽象の手段であるマクロ。

漠然としていますが、こういう理解でよろしいでしょうか。

以前 ruby の matz 氏が、マクロでできることはほとんど高階関数でできてしまう
と言っていましたが、決してそうではないですね。

今までマクロと言うと、パワフルだが汚いという負のイメージが強かったのですが、
今回それが変わりました。むしろ、関数抽象と補い合って Lisp の総体を支える
本質的なものだと感じました。今後もっとマクロを深く知りたいです。

ありがとうございました。

307 名前:デフォルトの名無しさん mailto:sage [04/09/15 01:29:34]
高尚なネタで盛り上がってるとろこスマン。
BKNL,TBNL,IMHO,UncommonWeb,AllegroServe+WebActions,CL-HTTPといろいろある
ウェブサーバ on CLなモノタチのなかでこのスレ住民のお勧めはどれなのか教えて欲しい。
できれば理由も。処理系はACLかCMUCLの予定です。

308 名前:デフォルトの名無しさん mailto:sage [04/09/15 10:05:40]
>>307
おれも知りたいな
ACL の WebAction はセミナー聞いただけだと
そう良くも悪くもなさげだった、ほとんど Apache Struts の焼直しって感じだけど
他のも Web 「アプリケーション」サーバーなのかしら?



309 名前:デフォルトの名無しさん mailto:sage [04/09/16 00:57:02]
スレの内容が高度すぎる…
初心者スレは良かった…

310 名前:デフォルトの名無しさん mailto:sage [04/09/16 04:28:41]
ちっとも高度じゃないよ。
分からないうちは飛ばしとけ。

311 名前:デフォルトの名無しさん mailto:sage [04/09/16 10:42:55]
>>309
大丈夫。あきらめなければそのうち、ちゃんとわかるようになるから。
シンプルなのが Lisp の身上。
スレの過去ログの、昔読んで分からなかったところが、少したつととても面白く
読めるようになります。経験者は語る。

-------------------
新山氏の日記に、久しぶりに Lisp のことが書かれている。
tabesugi.net/memo/2004/92.html#150242

新山氏は相変わらず冴えてます。読んで「うわー、そういう感じ、よく分かる」
と思った人も多いのではないだろうか。

312 名前:デフォルトの名無しさん mailto:sage [04/09/16 13:59:44]
>>306
> マクロでできることはほとんど高階関数でできてしまう

そこで高階関数と言っているのは、評価したくないコードブロックをラムダで
括ってしまうということを言ってるわけで、>>300 の前半の関数版に対して

;リストにアトムが含まれるか?
(define has-atom? (make-function (lambda (a b) (or a b)) #f))

と書けばよい、ということじゃない?


313 名前:デフォルトの名無しさん mailto:sage [04/09/16 15:44:06]
>>311
>「うわー、そういう感じ、よく分かる」
Lisp側から見て? それともPython側から?
ちなみに俺はSchemeもPythonも好きで両方使ってるけど,
Lisp側の意見はあまり共感できないなぁ.(マクロまんせーには同意するけど)

314 名前:311 mailto:sage [04/09/16 15:56:34]
>>312
確かに引数として与えたとき or は評価されないけれど、has-atom? の内部で
or ではなく、or に似た働きの関数になっちゃうでしょ? or に与えたい引数
の両方をまず評価してしまうから、リストを最後まで評価しないと止まらない。

>>313
Python 側。と言うか、外から見た Lisper の雰囲気。(私は Python 知らないので)

315 名前:312 mailto:sage [04/09/16 16:42:23]
>>314
あーそうか

(define make-function
  (lambda (operator null-value)
  (lambda (list0)
  (if (null? list0)
  null-value
  (operator (lambda () (not (pair? (car list0))))
  (lambda () ((make-function operator null-value) (cdr list0))))))))

(define has-atom? (make-function (lambda (a b) (or (a) (b))) #f))

こんな感じでどう?もしかしてまた勘違いしてるかな




316 名前:デフォルトの名無しさん mailto:sage [04/09/16 18:15:12]
>>315
今度はOK。つうか、煩雑で最初はよく分からんかった。
分かりやすいよう、遅延評価に直せるところを書き直してみた。
(かえって分かりづらい?)
やっぱりマクロのほうが分かりやすいと思う。

;;遅延評価版
(define make-function
 (lambda (operator null-value)
  (lambda (list0)
   (if (null? list0)
     null-value
     (operator (delay (atom? (car list0)))
          (delay ((make-function operator null-value) (cdr list0))))))))

(define has-atom? (make-function (lambda (a b) (or (force a) (force b))) #f))


それにしても、関数型言語方面の人が「Lispで遅延評価など書いておれるか!」と言ってるけど
気持ちがわかったような気がする。やっぱり煩雑だよね、これ。

317 名前:デフォルトの名無しさん mailto:sage [04/09/16 19:14:58]
リストの評価が途中で止まるのは、いずれもspecial form である or のおかげ
なのだから、or をそのまま渡せるマクロのほうが、はるかに自然。

or に仕事をさせるために、lambda や delay で囲んで、引数の強制的な評価を
回避させなければならない高階関数は冗長。

318 名前:デフォルトの名無しさん mailto:sage [04/09/16 19:23:34]
細かい話だけど、それぞれ1個目の delay と force 、要らないじゃん。

319 名前:デフォルトの名無しさん mailto:sage [04/09/16 22:43:03]
special-formをfirst-classにするってことは,
実行時にマクロ展開を行わせることになるよね.
そうすると静的スコープがグチャグチャになるような,ならないような….
あぁ,メタメタしてワケ分からん.

ところで,暗黙のforceを実装した処理系ってある?
暗黙のforceを実装してれば,遅延評価版>>316とかは,delay一つでよくなる.

320 名前:312 mailto:sage [04/09/17 00:45:57]
>>318
そうだね、 or の第一引数はかならず評価されることが決まってるから
delay する必要はないのか

>>316-317
冗長で分かりにくい、こんなコード書きたくも読みたくもない、というのはもちろん同意。
今回意地になってしまったのは >>306

> 以前 ruby の matz 氏が、マクロでできることはほとんど高階関数でできてしまう
> と言っていましたが、決してそうではないですね。

に反論したくなっただけdeth。テヘ


321 名前:デフォルトの名無しさん mailto:sage [04/09/17 09:16:08]
>>320
> 以前 ruby の matz 氏が、マクロでできることはほとんど高階関数でできてしまう
> と言っていましたが、決してそうではないですね。

これ,orとかの評価を遅延させるためのマクロのことを念頭に置いてるんですかね.
「できる」と「やりやすい」は違うし,だいたい,できないこともおおいじゃん...

322 名前:デフォルトの名無しさん mailto:sage [04/09/17 11:56:01]
やりやすくないとやりたくない.

323 名前:デフォルトの名無しさん mailto:sage [04/09/17 13:39:34]
>>321
マクロでしかできないことってどういうものがありますか?
マクロは興味はあってもとっつきにくいなあと思っています。
教えてもらえるとイメージが湧くかも。


324 名前:321 mailto:sage [04/09/17 13:57:18]
www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?Scheme%3a%a5%de%a5%af%a5%ed%a4%ce%b8%fa%cd%d1
マクロの応用方法を分類して解説しているので,参考になるのでは.

「宣言的コードにみせる」や「ミニ言語のうめこみ」あたりが
美しいマクロの使い方だとおもいます.

325 名前:デフォルトの名無しさん mailto:sage [04/09/17 14:19:47]
>>321
まさに去年の今頃、似たような話をしていた記憶が。懐かしい。
ちなみに matz 氏の発言ていうのはこの辺。
ttp://www.rubyist.net/~matz/20030915.html

何となくだけど、matz 氏の意図しているところは
「dolist って for-each でいいじゃん?」ていう程度の話な気がする。
遅延評価がどうとか call-by-name がどうとかってところまでは風呂敷は広げてない感じ。



326 名前:321 mailto:sage [04/09/17 14:38:04]
ああ,これって算符の記でやってた議論なんですね.しらなかった(赤面)
両者のスタンスの違いがよくわかりますた.


327 名前:デフォルトの名無しさん mailto:sage [04/09/17 22:04:43]
評価を遅延させるだけの目的でマクロを使うのはよくないと思う.
引数が評価されるかどうかが定義を見ないと判らないわけで,
むしろ可読性を損なっている気がする.
マクロはマクロを使わないとできないこと,例えばdefineを拡張して
パターンマッチできるようにするとか,そういう目的で使うべき.

328 名前:デフォルトの名無しさん mailto:sage [04/09/17 23:35:35]
Common Lisp使ってCみたくメモリ上のビット単位まで意識したコードって簡単に
書けますか? 書けるとしたらその方法が知りたいです。memory mapped I/Oの操作
みたいな低レベルな操作ができるのかな、ってのと、やっぱりそんな処理はCでヤレ、
そもそもLisp使ってやる内容じゃないだろ、って結論しかないのかを教えてくれるとうれしい。

329 名前:デフォルトの名無しさん mailto:sage [04/09/18 01:26:48]
素人でスマンが、Cで簡単に拡張ライブラリが書けるような
Lisp処理系を使う、って答えになるんじゃなかろうか。

330 名前:デフォルトの名無しさん mailto:sage [04/09/18 01:33:48]
最近の主なLisp処理系ならFFIでCのコードを呼べて楽よ。
>>328みたいなこともやればできそう。
でも分野的に、Cで書く方が直感的でメンテもしやすい気がしなくもないので、
そういうコードをCで書いてFFIで使うというのがいいんじゃないかい。




331 名前:328 mailto:sage [04/09/18 02:36:20]
レスどうもです。やっぱりFFI使ってCで書くのが定石なんですね。
Cltl2眺めててbit-vectorのオブジェクトの存在するアドレスを物理メモリにマップできれば
もしかして・・・と思ったのですが違ったようです。LispMachineとかだとできたのかなぁ。
データの圧縮とかビットマップインデックスみたいに素のLispが提供していないメモリ上のデータ構造を
ゴリゴリ扱いたいなぁ、と思ったらLisperの取る道はFFIしかないんですかね。それともマクロで
抽象化してarray :element-type (unsigned-byte 32)の上で操作するのでしょうか。

332 名前:デフォルトの名無しさん mailto:sage [04/09/18 03:06:04]
物理メモリにmapするには、もひとつOSの助けも必要だと思われ。
Linuxはユーザ空間にmemory mapped I/Oをmapできたんだっけか。
ユーザ空間にI/OをmapするAPIと、具体的な仮想アドレスのreferenceを
取得できるAPIをFFIで書いたらできるのかな。


333 名前:デフォルトの名無しさん mailto:sage [04/09/18 03:26:40]
結局そういうインタフェース作ったとして問題は参照方法だろ
さすがにメモリ走査とかはポインタないと辛い
Cでやった方が全然楽だし速いよ

(let (ptr (make-integer-ptr mem)) ;; ポインタの作成
(ref ptr) ;; 参照
(deref ptr value) ;; 逆参照
(inc ptr)

こんなことやってられっか?
実際は型の問題もあるし、もっと煩雑になる
そもそも演算子がないのが痛い

int *ptr = mem; // ポインタの作成
&ptr; // 参照
*ptr = value; // 逆参照
++ptr;

やっぱ記述量が割に合わない

334 名前:デフォルトの名無しさん mailto:sage [04/09/18 03:35:32]
餅は餅屋

335 名前:328 mailto:sage [04/09/18 03:55:28]
はぅあ。袋叩きにあってしまいましたな。記述量が割に合わないとかLisp向きじゃないよなぁ
とは思いながらも知らない世界があるかも程度の好奇心で聞いただけなのでした。

>>334 餅は餅屋
御意。いまも仕事でLispのコード書いてたんだけど、Lispで書いてるととにかく楽なんで
何でもかんでもLispで書けないかなとか思った私が阿呆でした。
どうでもいいけど、みんなこんな時間まで何やってんの?皆もデスマ?



336 名前:デフォルトの名無しさん mailto:sage [04/09/18 04:01:40]
Schemeで名前空間で名前を分類するようなことをしたいのですが、どういう方法を
取ればよいのでしょうか?
C++でnamespaceでモジュール全体を囲って名前の衝突が起きないようにして、
using namespaceで名前空間を使うというようなことです。
名前空間を階層化したりもしたいのです。


337 名前:デフォルトの名無しさん mailto:sage [04/09/18 04:22:51]
標準的な方法はないから
toplevelをletか何かで包んで必要な名前だけ外部に出すとか

(define proc1 #f)

(let ()
(define (proc1-sub1) ... )
(define (proc1-sub2) ... )
(set! proc1 proc1-sub1)) ;; export

あとは処理系依存だから、付属のマニュアルでも嫁

338 名前:デフォルトの名無しさん mailto:sage [04/09/18 05:32:43]
>>328
>>338 の言う通り、やってできなくはないと思う。mapしたアドレス値を
取得するのと、そのアドレスにアクセスするプリミティブは処理系
依存になるが。だがCでポインタを扱いなれてると、Lispでのアクセスは
冗長だね。マクロが使えることはメリットだけど。



339 名前:デフォルトの名無しさん mailto:sage [04/09/18 09:28:32]
>>336
処理系依存でよければmoduleシステムやなんやらを使うのがいいでしょう。

どうしてもportableでやりたいなら、top levelの束縛を変更する関数を
マクロで置き換えて、ほげほげとか。
って、top levelの束縛をマクロにするのはR5RS的にはだめなんだっけか...

340 名前:デフォルトの名無しさん mailto:sage [04/09/18 10:40:21]
スペースで区切られたテキストが以下のようにあったとして
A B C
D E F
↓(変換)
A
D

B
E

C
F

みたいな文章に整形するプログラムを作ろうと思ったのですが
いまいちエレガントにかけません
読み込むテキストファイルを"test.dat"として
以下のように書きました

(with-open-file (in "test.dat" :direction :input)
(let ((buff)
(str1)
(str2)
(str3)
(vstr))
(while (setq buff (read-line in nil))
(setq vstr (split-string buff "\t"))
(setq str1 (concatenate 'string str1 (first vstr) "\n"))
(setq str2 (concatenate 'string str2 (second vstr) "\n"))
(setq str3 (concatenate 'string str3 (third vstr) "\n")))
(format t "~A\n~A\n~A\n" str1 str2 str3)))

誰かアドバイスください・・・

341 名前:デフォルトの名無しさん mailto:sage [04/09/18 13:02:49]
縦読みデコーダでも作るの?


342 名前:340 [04/09/18 13:15:05]
>>341
そんな大層なものではなくて
練習用に書いているのですが・・・

上の例では3列と固定しているところを可変で
対応できるようにしたいのです
str1,str2,str3 とかやるのは格好悪いし・・
もっとすっきり書けませんかね?

343 名前:デフォルトの名無しさん mailto:sage [04/09/18 13:32:22]
下のコードはヒントにならない?
(mapcar #'list '(a b c d e) '(3 4 5 6 7))
=> ((a 3) (b 4) (c 5) (d 6) (e 7))



344 名前:340 [04/09/18 15:24:32]
>>342
有難うございます
で、さっそく以下のように書いてみたのですが、
結果が nil になってしまいます

(defun util (fname)
(with-open-file (in fname :direction :input)
(let ((buff)
(output))
(while (setq buff (read-line in nil))
(setq output
(mapcar #'list output (split-string buff "\t"))))
(mapcar #'(lambda (s) (format t "~A\n" s)) output))))

(util "test.dat")
nil

なぜ nil になってしまうのでしょうか?

345 名前:デフォルトの名無しさん [04/09/18 16:18:32]
whileの返り値



346 名前:デフォルトの名無しさん [04/09/18 18:07:39]
(defmacro for ((var start stop) &body body)
 (let ((gstop (gensym)))
  `(do ((,var ,start (1+ ,var))
     (,gstop ,stop))
     ((> ,var ,gstop))
   ,@body)))

これはOnLispに載っている "正しいforマクロ" (図42)
ですが、このgensymの例が何故正しいのかよくわかりません。

bodyの中にフリーなgstopが出てきたらやはり名前衝突を
起こしてしまう気がするのですが、私は何か勘違いして
いるのでしょうか。

347 名前:デフォルトの名無しさん mailto:sage [04/09/18 18:16:40]
>>344
(mapcar #'list nil '(1 2 3)) => nil だよ
まず output として '((A B C) (D E F)) を作ってこれを '((A D) (B E) (C F)) に変換する
と思えば良いんじゃない?
あんま考えてないけど↓
(defun util2 (output result)
(if (car output)
(util2 (mapcar #'cdr output) (cons (mapcar #'car output) result))
(reverse result)))

>(util2 '((A B C) (D E F)) '())=>((A D) (B E) (C F))


348 名前:デフォルトの名無しさん mailto:sage [04/09/18 18:45:50]
gensymはinternされない (システム内部の、名前からシンボルへの
対応表に登録されない) シンボルを作るので、このマクロの展開時に
作られるシンボル (#:G0031とか) と同じシンボルを外から与えることは
できない。(同じ名前にしてもシンボル自身は別オブジェクトなので
衝突しない)



349 名前:340 mailto:sage [04/09/18 18:56:21]
nil にリスト追加してもnilなんすね
また修正してみました
途中経過ですが・・・
(with-open-file (in "test.dat" :direction :input)
(let((buff)
(output '()))
(while (setq buff (read-line in nil))
(if (null output)
(setq output (split-string buff "\t"))
(setq output
(mapcar #'list
output
(split-string buff "\t")))))
output))

としたら2行だと上手くいきますが => ((A D) (B E) (C F))
3行目からは(((A D) G) ((B E) H) ((C F) I))
となってしまふ・・・
<<347 のように今度は再帰で考えて見ます

350 名前:デフォルトの名無しさん [04/09/18 19:24:40]
>>348
ああそうか!
` が付いて無いからマクロの展開時に (let) は消えるんですね
納得・・・ありがとうございました

351 名前:340 [04/09/18 19:48:28]
ようやく上手くいきました
良いLISPの勉強になりました

(defun util (filename)
(with-open-file (in filename :direction :input)
(let
((buff)
(output))
(while (setq buff (read-line in nil))
(if (null output)
(setq output (split-string buff "\t"))
(setq output
(mapcar #'(lambda (v1 v2)
(if (listp v1)
(append v1 (list v2))
(list v1 v2)))
output
(split-string buff "\t")))))
output)))

知恵を下さった皆さん有難うございました
もっとエレガントにいけるとかあったら
ぜひ教えてください

352 名前:ミミ [04/09/19 10:40:16]
Scheme の継続と、Win32 API のウィンドウ プロシージャ コールバック
って、共存可能だと思いますか?

353 名前:デフォルトの名無しさん mailto:sage [04/09/19 11:07:15]
不可能な理由がなかったら可能だよ。

354 名前:& ◆TACpYgPjX6 [04/09/19 11:17:07]
それがよくわからないんですよ。
だって、OS 側でどんな処理をしているか分からないじゃないですか。

たとえば WM_KEYDOWN ハンドラ内で継続を作成して、
一度そのハンドラを終了して OS に制御を返すでしょ。
そのあと WM_LBUTTONDOWN ハンドラ内で
先ほどの継続を呼び出すと、WM_KEYDOWN メッセージの処理が
再開されるわけですよね。

OS 側でスタック上のデータではない
グローバル変数をいじっていたとすると、
コンテキストがめちゃくちゃになって、
よくない気がするんです。

355 名前:デフォルトの名無しさん mailto:sage [04/09/19 11:26:55]
> OS 側でどんな処理をしているか分からない

分からない以上、可能だという確認ができないんじゃないか?



356 名前:ミミ [04/09/19 11:31:53]
いえいえ、今の私の知識ではわからないということなんです。
どなたか深い知識をご存知の方はいらっしゃらないかなと思いまして。

357 名前:デフォルトの名無しさん mailto:sage [04/09/19 11:33:02]
354の話で使いたい場面と、問題意識が少しわかったので
もう少し整理してから、その問題意識を中心に調べものしたらわかるのではないかな。
イベントハンドラまわりなんだよね。
;;; Windowsのことはよく知らないけど...


358 名前:& ◆TACpYgPjX6 [04/09/19 11:36:15]
実は Windows 専用 Scheme を作りたいと思っているんです。
特にシステム ハックをするためのツールを
Scheme でガンガン作りたいんですよねぇ。

コンセプトは
"Scheme as a better C."
"Scheme as a hacking tool."

359 名前:デフォルトの名無しさん mailto:sage [04/09/19 11:50:34]
で?

360 名前:ミミ [04/09/19 11:51:32]
協力してくれたらうれしい。
できたら使わせてあげるから。

361 名前:デフォルトの名無しさん mailto:sage [04/09/19 11:54:40]
面白そうではあるが,コールバックまで正常動作させようとすると
継続はおろかクロージャさえ厳しいだろうな…

362 名前:& ◆TACpYgPjX6 [04/09/19 11:56:17]
だいたいですね、Lisp 系の言語って、
どれもこれも Unix っぽいのがよくないと思うんですよ。
Perl や Python も同じなんですけど、
Java はちょっと違う感じ。

Windows みたいな素敵なシステムに、
Scheme みたいな素敵な言語があれば、
みんな幸せだろうなぁ、と思ってさ。

363 名前:ミミ [04/09/19 11:59:09]
すいません、どうしてクロージャが難しいのでしょうか。
何も OS が直接クロージャを呼び出すことは期待していないです。
間に C 関数をかませば問題ないですよね?

> 面白そうではあるが,
ありがとう。

364 名前:デフォルトの名無しさん mailto:sage [04/09/19 12:00:52]
PythonはMac出身じゃなかったっけ.
まぁ、それはともかく、Unixっぽいってどういうこと?

365 名前:デフォルトの名無しさん mailto:sage [04/09/19 12:13:05]
>>363
話の流れからすると,Win32APIを丸々wrapするんじゃなくて,
Cの関数を直接呼び出したりできる機構を用意しようってことだよね?



366 名前:& ◆TACpYgPjX6 [04/09/19 12:18:32]
一番大きなのは、コンソール (標準入出力) を前提としていること。

あと、いろんな Scheme 処理系をみてみても、
最初にサポートされるライブラリが POSIX ライブラリを移植したものとか、
GNU の readline たら curses たら、
/etc/network の存在を仮定したソケット ライブラリとか (Winsock にしてくれ)、
Windows で使うにはほとんどいらないものばっかりあって、
肝心の Windows 用のライブラリがないんですよ。

レジストリ アクセスや COM バインディングは必須でしょう。
もちろん ウィンドウ プログラミングができないとだめ。
(Unix では X がオプションだから困る)

あと、リソースのアクセスとか、シェル サービスへのアクセスとか、
さまざまな Win32 API をオブジェクト指向的にパックしたものとか
Win32 のセキュリティ機構は Unix と大きく異なっているから、
それを無理やり Unix 的に狭めても、使う気になれない。

Scheme だけで DLL を書くとか、サービス書くとか、
スクリーン セーバー書くとか、Scheme だけでデバドラ書くとか。
そんなのができない。

しようとすると、既存の Scheme に拡張機能を実装しないとだめで、
その Scheme 実装系の内部動作から把握しないとだめってことになる。
しかも Scheme 実装系自体が Unix を基盤としているので、
Windows 用に最適化されているわけでもない。

であれば、Windows 専用の Scheme 実装の上に
Windows 専用のライブラリを構築するほうが
ずっといいと思う。

367 名前:デフォルトの名無しさん mailto:sage [04/09/19 12:27:13]
うーん、Scheme.NETか?






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<286KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef