CommonLisp Scheme Pa ..
[2ch|▼Menu]
655:デフォルトの名無しさん
04/10/08 11:19:34
shiro さんの2004.10.07の文章で、
URLリンク(www.shiro.dreamhost.com)

以前から Lisper としての適性に関係があるとして、時々話題になっている、
アスペルガー症候群・高機能自閉症の、簡易テストが紹介されている。

「平均は16.4ポイントで、 32ポイント以上のうち8割はautism related disorder
だそうだ。私(shiroさん)は31ポイントだった」そうです。
URLリンク(www.wired.com)

自分でやってみたところ、慎重に回答したのに38ポイントだった。
しかし自分はヘタレ Schemer。ぜんぜんLisp能力に比例して無いじゃん…。

656:デフォルトの名無しさん
04/10/08 12:14:36
このテスト、人間関係が苦手である、うまく行っていないという項目が多いな。
だから、

・ Lisper として能力が高い
→・他言語のプログラマとしても成功する
→・周囲から尊敬を集める
→・人間関係が良くなる
→・このテストのスコアが下がる

Lisper としての能力と、このテストのスコアには、こういう負の相関が
働いている気がするのだが。

657:デフォルトの名無しさん
04/10/08 12:48:17
心理テストに気休め以上の意味があるとは思わん。

658:デフォルトの名無しさん
04/10/08 17:18:30
>>655
辞書引きながらやってみた。 24ポイント。
微妙に低くてチョトくやしい (w

659:655
04/10/08 18:40:48
念のために言うけど、このテストはまったく当てにならないと思うよ。
『on Lisp』をいつまでも読み進められない私がそれは保証できる。

だけどなんとなく、ほかの人の点数も知りたいのう。
冷やかしでトライしてくれた人、他にもいたら書き込んでください。
おながいします。

660:デフォルトの名無しさん
04/10/08 19:26:09
34。Lisp は好きだけど能力があるのかどうか……

661:デフォルトの名無しさん
04/10/08 19:27:47
emacs で動く scheme 実行環境はありますか?


662:デフォルトの名無しさん
04/10/08 19:51:11
>>659
自閉症スペクトラムのテストとしてはそこそこいい出来だと思うが。
親戚男性自閉症率高の趣味の Schemer で、40点。非人間的なものへ
のこだわりと認識能力で点数が出て、直接 Lisp と関係があるわけ
じゃないから。

>>661
M-x run-scheme では不満?


663:655
04/10/08 20:08:14
>>662
自閉症スペクトラムについては、まあ同意です。
自閉症には私も興味を持って、いろいろ調べてみたことがあります。

「当てにならない」と書いたのは、Lisper としての能力と、このテストの関連。

>>661
思い切って guile-emacs を導入するのはどうだろう?
使ったことはないけれど。

664:デフォルトの名無しさん
04/10/08 20:08:44
>>656
・ Lisper として能力が高い
→・でも別にプログラマとしては成功しない
→・周囲からも尊敬は集めない
→・人間関係も良くならない
→・このテストのスコアが上がる

Lisper としての能力と、このテストのスコアには、こういう正の相関が(以下略)

665:デフォルトの名無しさん
04/10/08 20:41:18
感O しないで AC になれなかったので,
せめて lisp で AC に近づこうとしています.
これが妥当な lisp の用途ということでよろしいでしょうか?

666:655
04/10/08 21:32:01
それにしても、当然のように「自閉症スペクトラム」という言葉を使う人も、
やはりこのスレにはいましたか。ポイントも私より上だし。

>>664
私はプログラマとして才能がなかったんで、Lisp を覚えて「普通の奴らに差をつけ」
ようとしたんだけど、Lisper としても才能がなかった。
しかも副作用として、それまでは面白かった Java がつまらなくなってしまった。

自分はダメだったけど、Lisperとして成功できる人なら、他の言語でも成功するのかと
思っていたのに、まさか逆だというのですか?!


>>665
私は感電と Lisp の経験者だけど、現状は前述のとおり。
でもいいのだ。Lisp は面白いから。
きっと Lisp は、ただ面白いためにあるのだ。


才能はさておき、こういうことに興味を持つことには、自閉症傾向は関係が
あるような気がしなくもない。

667:デフォルトの名無しさん
04/10/08 21:59:47
ACよりもSEXPになりたい。

668:デフォルトの名無しさん
04/10/08 22:13:30
この自閉症どもが

669:デフォルトの名無しさん
04/10/08 23:13:31
>>667
sexp が t になるには 8 歳までに (ry

670:デフォルトの名無しさん
04/10/08 23:36:39
     ∩
( ゚∀゚)彡 sexp!sexp!
 ⊂彡

671:デフォルトの名無しさん
04/10/09 00:47:43
Lispの才能と体重は正比例の関係があるらしいよ

672:デフォルトの名無しさん
04/10/09 00:51:02
>>671
デブヲタ発見。

673:デフォルトの名無しさん
04/10/09 01:16:40
sexpと体重は正比例の関係があるらしいよ

674:デフォルトの名無しさん
04/10/09 09:57:46
「on Lisp」の日本語版があるって聞いたんだがその本の日本語名ってなに?
'on' も 'Lisp'も一般的すぎて検索してもよくわからない・・・

本じゃなくてどこかのWebページなのか?

675:デフォルトの名無しさん
04/10/09 10:00:05
>>674
>>544

676:デフォルトの名無しさん
04/10/09 10:00:29
>>674
>>544

677:674
04/10/09 10:14:44
おお、サンクス!!
スレの真ん中あたりにあったのか・・・

#こう書くべきかな? (thanx 675 676)

678:デフォルトの名無しさん
04/10/09 11:11:51
>>671
なんとなく,才能は体重の逆数にあるような.
0 Kgで発散しますが,CLHS には inf が無いのでちょっと分かりません.

679:デフォルトの名無しさん
04/10/09 11:55:07
Gauche(ver 0.8.1)でGauche-gtk(ver 0.4.1)
やってるんですけど、
(gdk-font-load)が未定義の値って言われちゃいます。
なんで?



680:デフォルトの名無しさん
04/10/09 11:55:38
まだ4kgもないうちの甥っ子は天性のlisperなのかしら


681:デフォルトの名無しさん
04/10/09 13:47:02
大人になると、才能は錆付くんだよ。

682:デフォルトの名無しさん
04/10/09 17:12:00
SRFI40: A Library of Streamsを読んでて違和感を感じたので、それを文に
してみた。schemeのプロミスの話。感想きかせて。

members3.jcom.home.ne.jp/t-yam/promiseless.html

683:デフォルトの名無しさん
04/10/09 17:25:23
ブラクラ?

684:デフォルトの名無しさん
04/10/09 17:26:36
>>682 いいんじゃない? そもそもR5RSはdelayが特定の「プロミス型」を
返すことを要求していないから、そこで必要な時に必要なだけforceされる
処理系も許されてるんじゃないかな。(delayの返す値は「プロミスである」
とされているだけで、それが具体的に何なのかは未定義。さらに、
「プロミスとそれがforceされた値とを区別することは規格内ではできない」
とされているから、プロミスなんてユーザには見えない、っていう処理系
もありと。)

個人的にはimplicit forceしてくれた方がずっとプログラマに易しいと
思う。R5RSでそうなっていないのは、色々な遅延評価メカニズムを実装する
ベースとしての処理系実装も許しているからなんじゃないかな。色々
試してみたいときにはforceされるタイミングを制御したいことも
あるんじゃない?



685:デフォルトの名無しさん
04/10/09 17:31:52
具体的なコードを挙げると説得力が増すぞ。

686:デフォルトの名無しさん
04/10/09 17:42:30
delay/forceが無駄な仕様にみえて仕方がない。
Schemeの思想と背反する様な。
実際使う事あるの?

687:デフォルトの名無しさん
04/10/09 17:46:52
くまああああああ

688:682
04/10/09 17:47:40
レスありがとう。

>>684
R5RSの注意すべき点は、プロミス型があるかどうかではなくてプロミスが
オブジェクトであること(R5RS 4.2.5)だと思う。それが根本的な問題かと。

> forceされるタイミングを制御したいことも
ありそうだよね、これ。ただ、必要になったときに強制されるのだ、という
方が純粋なcall-by-needに近いようにも思う。

>>685
リンクたどればあるよ。


689:デフォルトの名無しさん
04/10/09 18:13:49
>>674
"On Lisp"とかぐーぐるさまに教えると次の検索で少しは幸せになれるんではなかろうか。

690:682
04/10/09 18:25:58
再レス。
>>684
> プロミスなんてユーザには見えない、っていう処理系もありと
あなたの言ってることがわかったw
R5RSのforceの解説の最後の方にそう書いてあるのね。完全に見落としてた。
thx


691:デフォルトの名無しさん
04/10/09 19:11:42
forceはpromiseにしか適用できない(かもしれない)のに、
promiseであるかどうか判別する手段が無い(かもしれない)。

つまり完全に評価順序が分かっててpromiseと値を混在させないように
プログラムが書けるときしか使えない。
でも遅延評価ではあらかじめ評価順序を知るのは一般にはとても難しい。
実用性が全然ないような。(>>616をさえ遅延評価で書くのに挫折…)

692:デフォルトの名無しさん
04/10/09 19:29:32
>>691
forceは何にでも適用できるよ。それは保証されてる。
promiseであるかどうか判別する手段はないかもしれない。


693:デフォルトの名無しさん
04/10/09 20:04:18
>>692
どこに書いてある? 

例えば
MIT Scheme

1 ]=> (force 1)

;The object 1, passed as an argument to force, is not a promise.
;To continue, call RESTART with an option number:
; (RESTART 1) => Return to read-eval-print level 1.

2 error>

694:692
04/10/09 20:48:54
あ、わりい。漏れの勘違い。
'may' だから、適用できるかどうかわからんのね。
なんだ、ますます使い勝手が悪いなあ。


695:デフォルトの名無しさん
04/10/10 02:59:20
>>691
関数的なもの、つまり副作用が無いものであれば評価順序に意味は無いはず。
そういうものと組み合わせてこそ promise の真価は発揮される。
一度評価したら二度目以降の force は必ず同じ値になるというのもそう。

とはいいつつも delay/force を使ったことないや。

696:デフォルトの名無しさん
04/10/10 17:26:47
>>695
> 関数的なもの、つまり副作用が無いものであれば評価順序に意味は無いはず。
間違い。それなら遅延評価なんて要らない。

そもそも副作用の話はしていない。>>691で言っているのは、
「評価順序が完全にわかってない場合、一度forceしてしまったものに
もう一度forceしてしまうことがあり、それがエラーになる(実装依存で)」
ということ。

697:デフォルトの名無しさん
04/10/10 17:46:22
何度 force しようが promise は promise のままでは?
force した結果の値を他で保持しておく必要無いんだし

698:デフォルトの名無しさん
04/10/10 18:25:57
691は「渡された値がpromiseかどうかわからないから念のためforceしとけ」
ってことができない、って言いたかったんじゃない?

>>695 正規順序と適用順序について調べるとよろし。


699:デフォルトの名無しさん
04/10/10 20:19:31
>>697
forceした結果を他の関数に渡さないと計算は進まないし、
delayし忘れると計算してしまう。
なにか自分でプログラミングしたら難しさがわかると思うけど。

自分が遅延評価のプログラムだと思うものをgoshで組んだ後
MIT Schemeにかけてそのまま動いたら、結構すごいことだと思うよ。

700:デフォルトの名無しさん
04/10/10 20:42:36
>>698
そうです。

全部promiseにしてしまえばいいのだろうけれど、
それには一から遅延評価の処理系を作るか、
それなりのライブラリを作った上で注意深くforce/delayを
利用しつつ目的のプログラムを作るか、
ということになって、どっちもかなりのオーバーヘッド。

すぐには計算して欲しくない所にだけ適当にdelayいれておいて後で
なんとかするというわけにはいかない。

701:デフォルトの名無しさん
04/10/10 21:07:36
>>655
微妙に訳が違ってないか?
Eighty percent of those diagnosed with autism or a related disorder
scored 32 or higher.

元訳:32ポイント以上のうち8割はautism related disorder
試訳: 自閉症やその関連の診断を受けた人の8割は、32ポイント以上だった。

つまりこれは、このテストが8割の診断者をカバーすると言ってはいるが、
普通の人がテストを受けて、スコアが高ければ自閉症だ、とは言っていないんじゃないか?

702:デフォルトの名無しさん
04/10/10 21:17:48
自閉症は黙ってろ

703:デフォルトの名無しさん
04/10/10 21:27:16
ACになろうとして
感電死

704:デフォルトの名無しさん
04/10/10 22:46:04
>>701
そのとおり。
つまり、テスト問題を
 1 + 1 = 2 は正しいか?
にすれば、
  Ninety nine percent of those diagnosed with autism or a related disorder
  scored fully.

705:ミミ
04/10/11 16:57:33
Unicode (UTF-16) ベースの Scheme 処理系を作る場合、
R5RS の read-char 手続きは、ポートから 2 バイトを読み取って Unicode 文字を返すのが
自然ですよね?1バイト読み取りのためには read-byte のような拡張手続きを用意して。
既存コードとの互換性がなくなると思いますけど。。。

706:デフォルトの名無しさん
04/10/11 17:18:08
read-charとかの関数の他に読み込む文字種を指定できるといいんじゃないかな

(set-input-char-set 'ネコミミモード)

(with-input-char-set 'ネコミミモード
(read)
)
=>ネコミミモードでーす

とか


707:デフォルトの名無しさん
04/10/11 17:53:02
read-char は「文字」を返すだけで、それがどんなエンコードだとかどんなサイズであるかなどは R5RS では規定されていない

708:デフォルトの名無しさん
04/10/11 17:53:35
CMUCL は,C++ の .so を呼べないのでしょうか?

//////////////////// a.cc
int foo (int a, int *b)
{
  int c;
  c = *b - 10;
  *b = a * 10;
  return c;
}
////////////////////

# g++-3.4 -shared -o a.so a.cc

;;;;;;;;;;;;;;;;;;;; a.lisp
(use-package "ALIEN")
(use-package "C-CALL")
(load-foreign "./a.so")

(def-alien-routine "foo" int
  (a int) (b int :in-out))

(foo 13 3)
;;;;;;;;;;;;;;;;;;;;

# lisp -load a.lisp -eval '(quit)'

とやると,(長いので分割)

709:708
04/10/11 17:56:00
; Loading #p"/xxxxx/a.lisp".
;;; Opening shared library ./a.so ...
;;; Done.

Undefined foreign symbol: "foo"
   [Condition of type KERNEL:SIMPLE-PROGRAM-ERROR]

Restarts:
  0: [CONTINUE] Return NIL from load of "a.lisp".
  1: [ABORT   ] Skip remaining initializations.

Debug  (type H for help)

(KERNEL:UNDEFINED-FOREIGN-SYMBOL-ERROR-HANDLER "<error finding name>"
                        #.(SYSTEM:INT-SAP #x3FFFC7E8)
                        #<Alien (* #) at #x3FFFC480>
                        (14))
Source: Error finding source:
Error in function DEBUG::GET-FILE-TOP-LEVEL-FORM:  Source file no longer exists:
  target:code/interr.lisp.
0] (quit)

710:デフォルトの名無しさん
04/10/11 18:58:09
a.soのシンボルをリストアップしてみりゃわかるよ

711:708
04/10/11 19:20:52
>>710
はじめてナノメートル nm しました.
うまくいきました! ありがとうございます.
今から >>710 に萌えます (;´Д`)


gcc で作ったやつと比較して,トンでもないシンボル名になっていました.
でもその名前で lisp コードに書き,アンダーバー `_' をハイフン `-' に変えて
使ってみると,正常に動きました.
シンボル名が変にならないようにする方法はこれから調べます.

712:デフォルトの名無しさん
04/10/11 19:35:31
>>705 see srfi-56


713:デフォルトの名無しさん
04/10/11 22:27:42
call-with-current-continuationについて教えてください.
多分誤解しているのだと思います.
たとえば,
(call/cc (lambda (k) (* 20 (k 30))))
   => 30
になると思います.
これを,
「kというprocedureがactiveになった時点で,それに
渡されるべき30という引数が返されたのである」と
理解していましたが,これは誤りなのでしょうか?
この考え方をもって既存のコードを読むと,実際に
返される値と異なる結果になってしまいます.
どこがいけないか,ご指摘願えますでしょうか.
よろしくお願いいたします.

714:デフォルトの名無しさん
04/10/11 22:55:04
kという手続きがxを引数に呼び出されると、
対応するcall/ccの返却値としてxが戻される。
もちろん後続の処理もcall/ccが普通に戻った場合と同じように続く。

715:デフォルトの名無しさん
04/10/11 23:08:44
>>713
「procedureがactiveになる」ってどゆこと?

716:デフォルトの名無しさん
04/10/11 23:24:50
>>713
Gaucheでの出力だけど...

(define m '())
(list 1 2 3 (call/cc (lambda (k) (set! m k))) 4 5 6)
--> (1 2 3 #<subr continuation> 4 5 6)
m
-->#<subr continuation>
(m 999)
--> (1 2 3 999 4 5 6)
(list 1 2 3 (+ 100 (call/cc (lambda (k) (set! m k)))) 4 5 6)
--> 継続と100は足せないというエラー
(list 1 2 3 (+ 100 (call/cc (lambda (k) (set! m k) 100))) 4 5 6)
--> 1 2 3 200 4 5 6
(m 500)
-->1 2 3 600 4 5 6
つまり継続を呼び出すときの引数でそれを作った(call/cc ...)が丸ごと置き換わると考えるととりあえずよいかもしれない。

うまい説明になってないかな^^?
(list 1 2 3 (+ 100 (call/cc (lambda (k) (set! m k)))) 4 5 6)
--> 継続と100は足せないというエラー
(list 1 2 3 (+ 100 (call/cc (lambda (k) (set! m k) 100))) 4 5 6)
--> 1 2 3 200 4 5 6
(m 500)
-->1 2 3 600 4 5 6
つまり継続を呼び出すときの引数で(call/cc ...)が丸ごと置き換わると考えるととりあえずよいかもしれない。

あまり説明になってないかな^^?

717:デフォルトの名無しさん
04/10/11 23:26:16
>> 715

713です.
「procedureが呼び出される」に訂正.

>> 714

ありがとうございます.
ということは根本的に間違えた考えではないと理解して,
コードを追い直しています.


718:716
04/10/11 23:27:55
書き込みの途中に継続を呼んでしまったようだ... ごめん m(_ _)m


719:デフォルトの名無しさん
04/10/11 23:45:56
>> 716

ありがとうございます.
実際に追っているコードを示した方が早いので,そうします.
たとえば,Kent Dybvig プログラミング言語Scheme (日本語版)
p.61に,call/ccのサンプルとして

(let ((x (call/cc (lambda (k) k))))
(x (lambda (ignore) "hi")))
=> "hi"

というのがありますが,これは結局
(call/cc (lambda (k) k) (lambda (ignore) "hi"))
と等価(でよいのでしょうか)ですね.
この式内の引数 (lambda (ignore) "hi")はprocedure
だから,答は本にあるように "hi" じゃなくて,その
procedure自体(#<user-defined-function> みたい)
になると思うのです.
しかし確かにguileなどでは本の通り "hi" と出ます.
問題はこのprocedure自体を返すのか,evalった結果を
返すのかの違いにあるのだと思いますが、「eval忘れ」
がどこかにあるのでしょうか?
ちなみに kawa ではエラーとなり確認できません.


720:デフォルトの名無しさん
04/10/11 23:47:02
>>711
>シンボル名が変にならないようにする方法はこれから調べます.

そいつはC++を使ってる限り無理だ。関数の多重定義を実現するために、
シンボルには型情報がくっつくようになってる。

721:デフォルトの名無しさん
04/10/11 23:47:17
継続(continuation)のメモ
URLリンク(www.opengroupware.jp)

722:デフォルトの名無しさん
04/10/12 00:03:24
719 です.

>問題はこのprocedure自体を返すのか,evalった結果を
>返すのかの違いにあるのだと思いますが、「eval忘れ」
>がどこかにあるのでしょうか?
は間違いですね。
問題はこのprocedure自体を返すのか,呼び出した結果を
返すのかの違いにあるのだと思いますが、「呼び出し忘れ」
がどこかにあるのでしょうか?
の意味です。


723:708
04/10/12 00:04:17
>>720
なんと,,,そうですか.今ちょっと調べ疲れていたところでした.
どうもありがとうございました.
まあ lisp コードなんてすぐ修正できてしまうからいいんですよね!

724:デフォルトの名無しさん
04/10/12 00:13:42
>>719
最初に (x (lambda (ignore) "hi")) を評価するとき x は継続であり、それは
「最初の (call/cc (lambda (k) k))」から戻ってきて、返却値を x に bind し、let の body を評価する」
という継続である。
なので、これを評価すると最初の (call/cc (lambda (k) k)) から (lambda (ignore) "hi") が返却され、
これが x に bind され、(x (lambda (ignore) "hi")) が再度評価されることになる。
二度目に評価されるとき、x には (lambda (ignore) "hi") が bind されているので、これはつまり
((lambda (ignore) "hi") (lambda (ignore) "hi"))
ということになり、最終的に "hi" が返却される。

725:デフォルトの名無しさん
04/10/12 00:34:47
訂正
719の中の置換したコードは
((call/cc (lambda (k) k)) (lambda (ignore) "hi"))
のつもりでした.

>>724
ありがとうございます.最終的に
((lambda (ignore) "hi") (lambda (ignore) "hi"))
に置換されるのがミソのようですね.
まだまだSchemerになれていないので,724をなぞって
ゆっくり考えます.ありがとうございました.


726:デフォルトの名無しさん
04/10/12 01:59:29
>>723
extern "C" {
ネコミミモード
};

727:716
04/10/12 02:43:54
おれが安易に「丸ごと置き換わると考えるととりあえずよいかもしれない」なんて書いちゃったのは良くなかった。ごめんなさい m(_ _)m

置換で考えると上手くない場合もあるんだ。
例えば、

(let ((c 100))
(let ((x (call/cc (lambda (k) k)))) ;<- @1
(let ((c 200))
(x (lambda (n) (+ 1 c)))))) ;<- @2
--> 201

の (call/cc (lambda (k) k)) を単純に (lambda (n) (+ 1 c))に置き換えて考えてしまうと

(let ((c 100))
(let ((x (lambda (n) (+ 1 c))))
(let ((c 200))
(x (lambda (n) (+ 1 c))))))
--> 101

となって結果が合わなくなってしまう。

これは@2のlambdaで作られた#<closure>は@1に送られるけど、その環境は@2を持っているということが単純な置換で考えると消えてしまうからなんだ。
というわけで、716は忘れてください ^^;

728:デフォルトの名無しさん
04/10/12 09:57:42
スコープだけじゃないね。
(let ((x 0))
  (let ((c (call/cc (lambda (x) x))))
    (set! x (+ x 1))
    (c (lambda (y) x))))

(let ((x 0))
  (let ((c (lambda (y) x)))
    (set! x (+ x 1))
    (c (lambda (y) x))))
はちがうし。
あたかも置き換えたかのようにジャンプするというか・・・。

729:デフォルトの名無しさん
04/10/12 20:10:09
713です.
多くの丁寧な follow-up をありがとうございます.
call/ccはSchemeらしいところだと思うのですが
それだけ奥が深いですね.
何せ midnight programmer なものですから,
これから寝るまで頭をひねって考えます.
今後ともよろしくお願いします.

730:デフォルトの名無しさん
04/10/12 20:27:57
schemeの継続って、プログラムの最小限要素をくくりだすのはいいが
そのためにやたらコストの高いものを導入してしまったという感じがする。
Smalltalkでの何でもかんでもオブジェクトとメッセージに近いものがある。
継続そのものが便利なときもあるけど、なくてもほとんど困らない。


731:デフォルトの名無しさん
04/10/12 20:31:45
継続抽出は銀の弾丸です


732:デフォルトの名無しさん
04/10/12 20:44:17
ほんとにそうなら継続のある言語がとっくに天下をとってると思う。


733:デフォルトの名無しさん
04/10/12 21:44:11
悪い方が良い法則。

734:デフォルトの名無しさん
04/10/12 22:35:38
おまえらただ継続継続いいたいだけちゃうんかと。
継続なんて極力使わない方がいい。
gotoがよりパワフルにそしてわかりにくくなったものだから。
銀の弾丸どころかソフトウェアエンジニアリング的には狼男だ。

735:デフォルトの名無しさん
04/10/12 22:39:36
例外処理のような上手い使い方ならいいんだけどね

736:デフォルトの名無しさん
04/10/12 23:02:34
ちんちんかゆいーー!

737:デフォルトの名無しさん
04/10/12 23:03:46
gotoが悪ならthreadなんて巨悪だな

738:デフォルトの名無しさん
04/10/12 23:04:48
>>736
cut しろ


739:デフォルトの名無しさん
04/10/12 23:35:23
>>737
threadとgotoは比べるもんじゃないだろ。
threadは基本的に代えがきかない。

740:デフォルトの名無しさん
04/10/13 03:12:19
The Seasoned Schemerの継続の説明らしい章を読んでます。
で、質問なんですが、この本の中では継続を「call/cc」じゃなくて
「letcc」(schemeの場合)、「throw」「catch」(CommonLispの場合)で
説明してるんですけど、これらは等価なものなんですか?


741:デフォルトの名無しさん
04/10/13 03:30:06
>>740
shiroさんのなぜ Scheme には return がないのか
URLリンク(www.shiro.dreamhost.com)
を読むとその辺がわかるかも。

742:デフォルトの名無しさん
04/10/13 10:25:44
continuationとgotoは比べるもんじゃないだろ。
continuationは基本的に代えがきかない。


743:デフォルトの名無しさん
04/10/13 14:30:21
はっきり言って、continuation≒gotoだよ。認めたくないだろうけどね。
gotoでcontinueもbreakもreturnも出来るじゃん、美しい!って悦に入ってるのが
schemer

744:デフォルトの名無しさん
04/10/13 16:12:52
だがそれがいい

745:デフォルトの名無しさん
04/10/13 16:21:01
>>742
おうむ返しだけだと馬鹿にしか見えませんよ。

continuationはやろうと思えばいくらでも書き換えられる。
書き換えたらフラグだらけになったり、
巨大な関数になったりしてして醜いから、使う、というものでしょ。
もちろんそういうときに使うのはいいけど、
できるときはwhileとかforとかmacroにしたほうがいいだろう。

threadはthreadを使わずに同じ機能を実現することが難しい。
特にthreadのどれか一つが死んだりしても他のthreadが監視しておいて
処理できる、という能力はエミュレートできない。
エミュレートだとスケジューリングがうまくいくように一単位の
処理時間をコントロールできないといけないし。

746:デフォルトの名無しさん
04/10/13 21:25:49
ケイゾクに恨みでもあるんですか?

747:デフォルトの名無しさん
04/10/13 21:57:42
色んな意味でコストがかかるところ。


748:デフォルトの名無しさん
04/10/13 22:54:32
>>746 ないけど?

749:デフォルトの名無しさん
04/10/14 00:13:10
threadだって高速に処理切り替えてるだけだから、
gotoで出来ないことはない。

750:デフォルトの名無しさん
04/10/14 00:39:00
スレッドと継続は全く別個の独立した概念であり、対立するものでもないのに何をムキになってるんだろう。


> 書き換えたらフラグだらけになったり、
> 巨大な関数になったりしてして醜いから、使う、というものでしょ

それこそ継続という概念が primitive なものであるということであり、scheme らしいところでは?
primitive なものさえあれば他の機能はそれらを組み合わせてできる。美しい。
例えば、コルーチン程度であれば call/cc で簡単に実現できる。

751:デフォルトの名無しさん
04/10/14 00:54:20
コルーチン程度しかできない、の間違いでしょ

752:デフォルトの名無しさん
04/10/14 01:06:04
Rubyの継続の実装はスレッドと同じだそうですよ
URLリンク(i.loveruby.net)

753:デフォルトの名無しさん
04/10/14 01:44:06
>>749
gotoでどうやって
> 特にthreadのどれか一つが死んだりしても他のthreadが監視しておいて
> 処理できる、という能力はエミュレートできない。
するんだ?
そしてどうやって一つの処理単位がCPUタイムを食いすぎないことを保証するんだ?
> エミュレートだとスケジューリングがうまくいくように一単位の
> 処理時間をコントロールできないといけないし。

>>750
> スレッドと継続は全く別個の独立した概念であり、対立するものでもないのに何をムキになってるんだろう。
じゃああなたが>>737>>749を説得して上げてください。

754:デフォルトの名無しさん
04/10/14 01:45:11
gotoさえ使えば、breakもcontinueもreturnもいらないのはもちろん、
スレッドも関数もいもいらない。こういう機能はgotoを組み合わせてできる。
美しい。

755:デフォルトの名無しさん
04/10/14 01:53:27
>>750
美しかろうがどうだろうが、
「継続を無闇に使うべきでない」という事実には変わりはないな。

756:デフォルトの名無しさん
04/10/14 01:54:45
アセンブラにすりゃただのジャンプ命令。
ジャンプ命令使わずにアセンブラでプログラム組めるわけが無い。
即ち、息をするようにgotoを使え。

757:デフォルトの名無しさん
04/10/14 04:40:12
引数つきgoto

758:デフォルトの名無しさん
04/10/14 08:16:21
〉〉753OSやリアルタイム制御の本みれば書いてあるよ。つーか知らないの?

759:デフォルトの名無しさん
04/10/14 08:28:20
ヘタレLisperと本物のプログラマを隔てるOSという一つの壁

760:デフォルトの名無しさん
04/10/14 08:29:07
>>736-738
Prologの話?

761:デフォルトの名無しさん
04/10/14 09:24:37
まだちんちんかゆいよーー!
なぜか皮が膨らんできてる・・・

762:デフォルトの名無しさん
04/10/14 11:39:34
>>751
ユーザモードのスレッドは、本質的にはコルーチンと同等だけど?

763:デフォルトの名無しさん
04/10/14 16:06:08
コルーチンって何?

764:デフォルトの名無しさん
04/10/14 16:18:27
>>763
URLリンク(www.google.com)

765:デフォルトの名無しさん
04/10/14 17:26:42
>>762
ユーザーモードのスレッドは必ずしもそうでないと思うけど、
ユーザーモードのスレッドライブラリはそうだね。で、それが何か?


話は変わって、
そもそもSchemeの継続ってプリミティブか?
単にCPSで書けばいいだけじゃないの?こっちはどんな関数型言語にもできるし。

766:デフォルトの名無しさん
04/10/14 17:43:15
機械語のライブラリを実行中に継続を取ってきても
きちんと動くように要請してるんじゃない?

767:デフォルトの名無しさん
04/10/14 20:38:44
>>765
なんでそこに CPS が出てくるのか意味がわからない

768:デフォルトの名無しさん
04/10/14 20:45:57
>>768
Continuation Passing Style のことだよ?

769:デフォルトの名無しさん
04/10/14 21:25:50
>>767 の言いたいことを推測。

CPSで継続を陽に扱うには、最初から全部CPSで書かなくちゃならない。
CPSで書かれていないコードから呼ばれるコードで継続を取り出したかったら
call/ccはプリミティブにならざるを得ない。

…ってなとこか?
CPSでもMonadみたいな形で継続を隠すことはできるけど、それだって
最初からそのつもりで書いてないと。

個人的には、Schemeの継続は言語の実験をするための道具って
感覚が強いな。




770:765
04/10/14 21:44:13
>>769
言語の要素のプリミティブじゃなくて、
>>750
> それこそ継続という概念が primitive なものであるということであり、scheme らしいところでは?
> primitive なものさえあれば他の機能はそれらを組み合わせてできる。美しい。
の話。

(Schemeの)継続なんて無くてもCPSで書けば、gotoでもコルーチンでも
call/ccでも(w実現できるんだから、プリミティブな(基底をなす)機能ではないんでは?
ということ。

> 個人的には、Schemeの継続は言語の実験をするための道具って
> 感覚が強いな。
同意。

771:デフォルトの名無しさん
04/10/14 22:03:36
やたら継続を美しいと賛美しているのは、つい最近大学の
講義で継続を知って嬉しくなってる厨房だよね?

772:デフォルトの名無しさん
04/10/14 22:11:31
>>771
はい。

773:デフォルトの名無しさん
04/10/14 22:26:47
四角いタイヤでも目盛がついていれば長さを測ったりできて便利かもしれんが、
それで高速道路を走るのは無理だ。

774:デフォルトの名無しさん
04/10/14 22:37:43
で?

775:デフォルトの名無しさん
04/10/14 22:42:13
ちんちんかゆいーー!

776:デフォルトの名無しさん
04/10/14 22:44:58
>>775
切っとけ。

777:デフォルトの名無しさん
04/10/14 23:38:01
>>770
だから?基底をなす機能しか使っちゃいけないなら、
ラムダだけ使えば?
理論上は統べての計算はラムダ式で可能なんだから、


778:デフォルトの名無しさん
04/10/15 00:28:51
継続がプリミティブだからエライと言い出した
のは継続厨房でしょうが

779:デフォルトの名無しさん
04/10/15 01:15:03
だからつかわなきゃいいじゃん
threadだろうがcall/ccだろうが理解してない
人間がつかうと危険なのは当たり前。

780:デフォルトの名無しさん
04/10/15 01:20:39
>>778
エライなんて誰も言ってないよ

781:デフォルトの名無しさん
04/10/15 10:39:17
>>777
基底をなす機能しか使っちゃいけないなんて誰も言ってないよ。

>>779
理解している人間が使ったって危険なんですが。
というか、誰が使っても危険なものだということを理解していない人間は
理解している人間ではないでしょうね。

782:ミミ
04/10/15 14:26:27
>> 個人的には、Schemeの継続は言語の実験をするための道具って
>> 感覚が強いな。
>同意。
私も同意。
例外処理のような代替機能があれば十分だと思う。

783:デフォルトの名無しさん
04/10/15 16:26:43
どういう場合になにが危険といってるの?実装といっしょにあげてみてよ。

784:デフォルトの名無しさん
04/10/15 17:19:01
>>782
で、言語の実験で良い結果が得られたらその度に代替機能を実装してくの?

785:デフォルトの名無しさん
04/10/15 17:29:19
>>783
危険っぽいコード
(define go #f)

(call/cc (lambda(cc) (set! go cc)))

(call-with-input-file "foo" (lambda(port) (go port)))


はわわ〜

786:デフォルトの名無しさん
04/10/15 17:32:26
>>784
パフォーマンスを上げたいなら専用化した方がいいからね。
限定的な継続にして万能な部分を切っていく。
VBのバリアント型みたいなものだよ。

787:デフォルトの名無しさん
04/10/15 17:45:17
>>784
良い結果がって言うよりさ、そもそも言語の設計で「良い悪い」を
判断するのって使ってみないとわからんわけじゃん。で、処理系
ネイティブに実装する方式だと、その処理系を使ってる人しか
試せない。だけどSchemeの場合、かなり凝ったことまで言語組み込み
のプリミティブを組み合わせで書ける。そしたら、R5RS準拠の
処理系ならどれでもその提案を試してみることができるわけだ。

こいういう場合に使われるcall/ccなんかは、むしろ提案する
言語機能の仕様記述なわけよ。ところが、Schemeの場合は
その仕様記述が動かせるプログラムになる。


788:!= 782
04/10/15 18:26:51
>>784
そう。実装してく。
whileやらbreakやらgeneratorやらに抽象化してそれを安全に使う。
call/ccはそれを作る道具であって、call/ccのスパゲッティを毎回
ほどいて、俺には解けるから危険じゃないとか言って喜ぶための
ものじゃないと思うね。
上手い抽象化を考えたりその抽象化を実装したりするのに頭をつかおう。

789:ミミ
04/10/15 18:27:43
>>784
実用上の開発では言語実装にまで遡って設計の見直しを図ることは稀でしょう。

もちろん継続があったらあったらでよいと思いますが、
C における goto よろしく、大規模な開発では原則として禁じるのが妥当ではないかと。
ソフトウェア工学上は継続は狼男だと言っている方がいらっしゃいましたが、
その視点におけるその意見には同意するということです。

>>785
それは継続の問題というよりも、
プログラミングの腕の問題という気が。。。
do でも論理エラーがあれば無限ループが書けるわけだし。

>>786
>パフォーマンスを上げたいなら専用化した方がいいからね。
>限定的な継続にして万能な部分を切っていく。
これに同意。
Scheme に継続しか用意しないというのは実用的ではないという感じがします。


790:デフォルトの名無しさん
04/10/15 19:46:48
「実用的な」制御構造がいずれも継続の上に(マクロで?)構築した
ライブラリとして書けるっていうのがSchemeの主張なんじゃないの?

791:デフォルトの名無しさん
04/10/15 19:52:56
話がループしているのは継続のせいですか?

792:デフォルトの名無しさん
04/10/15 20:06:32
じゃあ高速な継続の実装の仕方でも考えるかい?

793:デフォルトの名無しさん
04/10/15 20:35:42
>>791
gotoのせいです。

794:デフォルトの名無しさん
04/10/15 21:18:32
>>790
そう。
パフォーマンスとかが必要ならそれぞれの実装系においてライブラリ部分をCとかで実装していけばよい。

795:デフォルトの名無しさん
04/10/15 22:36:02
結局Schemeは非実用的ということですね

796:デフォルトの名無しさん
04/10/15 22:39:54
わざわざ去勢する必要もなかろう

797:デフォルトの名無しさん
04/10/16 01:39:19
CommonLispのマクロについての質問。
マクロはコンパイル時に評価を行う、ということは、コンパイルプロセスを
実行プロセスから分離することはできない、ということでOKでしょうか?
また、関数の中でマクロが定義されている場合、関数が呼び出される度に
マクロ展開(とコンパイル)が行われるのでしょうか?


798:デフォルトの名無しさん
04/10/16 01:58:24
どういう動作をすると思ってるの?

799:797
04/10/16 02:06:33
実行とコンパイルがインターリーブしていて、マクロの展開関数の中
から他の変数なんかも参照できる。その変数の値によって、展開の結果
が変わるかもしれない...というふうに"思って"います。

根本的に間違ってますか?


800:デフォルトの名無しさん
04/10/16 03:39:45
継続の話。

Kawa(Java による Scheme 実装)の継続は例外処理(try - catch)
によって実装されているね。確か大域脱出しかできなかったような気
がする(Common Lisp の block 相当)。

実際、おれの場合、大域脱出くらいでしか継続は使ったことないな。

801:デフォルトの名無しさん
04/10/16 04:37:48
>>797
>コンパイルプロセスを実行プロセスから分離する
lispには eval関数の様に実行時に式を評価する仕組みがあるので
コンパイル環境と実行環境を分離するのは難しいと思う。
でもこの話は、マクロとは関係ないような気がする。

>関数の中でマクロが定義されている場合
関数内でマクロを定義した場合の動作など考えたことが無かった。
で、やってみた。

;; 関数定義
(defun test (x)
(cond ((equal x 1) (defmacro m () 10))
((equal x 2) (defmacro m () 20))
(t nil))
(m))

;; 実行結果 ・・・ clisp の場合
(test 0) => 20
(test 1) => 20
(test 2) => 20

;; 実行結果 ・・・ xyzzy lisp の場合
(test 0) => 関数が定義されていません: m
(test 1) => 10
(test 0) => 10
(test 2) => 20
(test 0) => 20

xyzzyではマクロ展開を実行時に行っていて、clispでは関数定義時に
行っているようだ。CLtL2 的にはどうなっているんだろう?

802:デフォルトの名無しさん
04/10/16 08:26:44
重複定義でエラーが正解

803:デフォルトの名無しさん
04/10/16 09:41:37
>>801
その例は実行時までプログラムの意味が決まっていないよね?
そういうマクロはたとえ可能としても悪いマクロだと思う
(実際おれは不可能と思ってたし)
役に立つ場合って何かあるかな?

804:デフォルトの名無しさん
04/10/16 15:10:07
>>797
> また、関数の中でマクロが定義されている場合、関数が呼び出される度に
> マクロ展開(とコンパイル)が行われるのでしょうか?

コンパイルされたコードの中でのマクロ展開はコンパイル時に行われて、
実行時には再度行われない、てことになってます。
ですから、関数内でマクロを再定義するようになっていたとしても、
展開に使われる手続きはコンパイル時の環境にあるものになるはずです。
コンパイルしない場合には、何時、何度展開されるかは実装依存です。
cf. URLリンク(www.lisp.org)

>>801
xyzzy でもコンパイルすると clisp と同じ結果になりますね。
でもいまいちピンとこない結果だなあ。
(defmacro m () 20) は展開時には、つまりコンパイル時であれ関数定義時であれ、評価されませんよね?
だったら (m) は展開できない気がするんですが。勘違いしてる?

805:ミミ
04/10/16 15:19:43
> (defmacro m () 20) は展開時には、つまりコンパイル時であれ関数定義時であれ、評価されませんよね?
リーダが読み取って、最適化された内部構造体に変換するときに、
ついでに defmacro を評価してしまうという実装はあり得ると思う。
(そんな処理系を見たことがある気がする。)

その場合、最後に出てきた m の定義によってオーバーライドされてしまうので、
上記のような結果になるのでは。

806:804
04/10/16 15:34:00
>>805
あーなるほど、それなら納得いきますね。
確かに普通それで問題ないでしょうし。

807:デフォルトの名無しさん
04/10/16 16:17:58
そういうマクロはエラーにして欲しいなあ。
eval介入するならともかく、使い道なんてないでしょ。


808:デフォルトの名無しさん
04/10/16 17:47:56
Gaucheはエラーになった

809:デフォルトの名無しさん
04/10/16 18:00:35
>>808
GaucheってSchemeでしょ?
Scheme的には>>801て文法的にありえんし…
mのスコープが意味不明。

810:デフォルトの名無しさん
04/10/16 18:27:24
>>797-799
> また、関数の中でマクロが定義されている場合、
これって macrolet のことを言いたいのかなあ、とふと思った。

> 実行とコンパイルがインターリーブしていて、マクロの展開関数の中
> から他の変数なんかも参照できる。その変数の値によって、展開の結果
> が変わるかもしれない...というふうに"思って"います。

これについては、こんな例もあるかな。

(defvar *foo*)
(defmacro %foo (x)
`(,(if *foo* 'car 'cdr) ,x))
(defun foo (ls key)
(let ((*foo* key))
(%foo ls)))

として、

(let ((ls '(a b c)))
(values (foo ls t)(foo ls nil)))
=> ? , ?

とりあえず今手元にある xyzzy では、コンパイルしないと a , (b c)、
コンパイルするとコンパイル時の *foo* の値によって a , a or (b c) , (b c) が、
更に *foo* の値が未定義だと (b c) , (b c) が返ってきました。
……しかし、どうにも病的な例しか思い浮かばないなあ。

811:デフォルトの名無しさん
04/10/16 20:26:58
letがないものが条件コンパイルのイディオムとして使われて
てもよさそうだと思ったんだけど、そうでもないのかな?

812:797
04/10/16 22:43:41
コンパイル時の環境・値をキーワードにしてHyperSpecを必死になって
読んで、部分的な理解を得ました。

マクロ展開のようなコンパイル時に実行される式はevaluation env.のもと
で評価され、そうでない本当に実行時に実行される式はrun-time env.のもと
で評価される。で、evaluation env.とrun-time env.が同一である保証は
無いと。
私の場合、この二つが同一と仮定していたので、797の発言になったわけ
ですね。実際は、run-time env.の中の束縛とは異なるかもしれない束縛を
evaluation env.に加えてやることでコンパイルプロセスを実行プロセスから
分離していると。
後は、コンパイルの過程でevaluation env.がどのように構築されていくのか
が解ればいいのですが、これも理解に時間かかりそう。

>>810
まだ文法に自信がないですが、こんなのなら病的ではないかと。
期待通りには振る舞わないみたいですが。

(defun debug-print (form value) ...)
(defvar *do-debug*)
(defmacro debug-value (form)
(if *do-debug*
(list debug-print `(quote ,form) form)
form))


813:Ruby >>>>>>>>>>>>>>>Scheme
04/10/17 06:09:54
Scheme を駆使して、「普通のやつらの上を行け」るのは、(少なくとも現状では、そして恐らく永久に)ごく一部のプログラマであって、
普通のプログラマが少しでも「普通のやつらの上を行け」るのは、Ruby になるような気がしています。
URLリンク(jp.rubyist.net)

814:デフォルトの名無しさん
04/10/17 06:26:35
結局のところ、CommonLispでマクロを安全に使うには、
(1)トップレベルで定義する。関数内では定義しない。
(2)同名のマクロの再定義はしない。
(3)スペシャル変数等の環境で動作が変わるマクロは書かない。
ということですか?

815:デフォルトの名無しさん
04/10/17 10:15:21
ものをちゃんと理解する、が一番じゃないかな。
まあ理解できないからこそ安全に〜とか言ってるんだろうけど。


816:デフォルトの名無しさん
04/10/17 11:04:12
>>815
それなりの指針を与えることは、有益だとおもうけどどうかな。
だれだって最初は初心者な訳なんだし。

817:デフォルトの名無しさん
04/10/17 11:11:48
>>816
指針としては、

マクロは単に式を変形する
・ソースを短かくするために書け
・いつ式が変形されたか気を付けろ(コンパイル時、実行時、再定義に注意)

って基本を叩きこめば十分じゃないか?まだあるかな?

818:デフォルトの名無しさん
04/10/17 11:52:18
>>816
> だれだって最初は初心者な訳なんだし。

これってよく使われるフレーズだけど全然言い訳になってないよな。
最初は初心者でも自力修得できる奴はなんぼでもいる。


819:デフォルトの名無しさん
04/10/17 13:24:58
>>813
おそらくはマクロ等を駆使することで、
「問題領域における問題の記述とコードが同一になる」 Lisp/Scheme すげえ!
って思うんだがどうよ?

820:デフォルトの名無しさん
04/10/17 15:23:24
>>817
>・ソースを短かくするために書け
これは同意できない。
結果としてソースが短くなるケースが多いとしても、ソースを短くすることは
マクロを書く目的にはなり得ません。

821:デフォルトの名無しさん
04/10/17 17:30:59
あんたにはならなくても俺はなるな

822:デフォルトの名無しさん
04/10/17 17:59:41
結果として短くなるのと、短くするのを目的として使うことを混同してませんか?

823:デフォルトの名無しさん
04/10/17 18:11:15
>>818
わからないことを責めてはいけないとおもう。
わかろうとしないことだとしてもそうだと思う。
そういう人を取り込むことが言語のすそのを広げることになるんじゃないかな。

824:デフォルトの名無しさん
04/10/17 18:14:49
>>821, 822
ソースコードの性質によるのかな〜と思うけど、どうかな。

長く、広く使われるコードであれば、直感にあう抽象化を
するためにマクロを使うべきだろう。
けど、テストコードなんかの場合はとにかく楽をするために
マクロを使っても良いように思う。

825:デフォルトの名無しさん
04/10/17 18:31:27
>>813
言語に「上下」があるわけではないと思うけどなぁ。

俺は ruby も好きだけど、scheme で書いてる時とは気分が違うよね。
なんつうか、ruby は relax しながら書くけど、scheme だと、集中して
研ぎ澄まされてく感じがする。抽象的だけどさ。


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

5063日前に更新/286 KB
担当:undef