質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
LISP

LISPはプログラミング言語の一種であり、関数型言語に分類されています。 特徴として、括弧を多様する独特の構文を持ちます。

Q&A

解決済

1回答

1484閲覧

Gauche(Scheme)継続とloadでIO-CLOSED-ERROR

vc3000

総合スコア196

LISP

LISPはプログラミング言語の一種であり、関数型言語に分類されています。 特徴として、括弧を多様する独特の構文を持ちます。

0グッド

0クリップ

投稿2015/10/17 14:47

編集2015/10/17 14:48

以下のコードでgosh b.scmと実行すると

hoge *** IO-CLOSED-ERROR: I/O attempted on closed port: #<iport(closed) ./a.scm 0x2235240> Stack Trace: _______________________________________

というエラーが出ます。
どうしてポートが閉じられた状態になるのでしょうか?

a.scm

lang

1(define (hoge) 2 (print "hoge") 3 (exit-cont) 4 (print "not reach here")) 5 6; 終了地点を保存しておく 7(define exit-cont (undefined)) 8(call/cc (lambda (cont) 9 (set! exit-cont cont)))

b.scm

lang

1(load "./a.scm") 2 3; ↓これをコメント解除するとエラーはでなくなる 4;(call/cc (lambda (cont) 5 ;(set! exit-cont cont))) 6 7(hoge)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Gaucheのloadは、(今のところ)実行がいかなる形であれ中断された場合にポートを閉じるからです。

call/ccはプログラムの実行状態を「セーブ」すると考えることができますが、グローバルなリソースの状態は「セーブデータ」には含まれません。ポートはグローバルなリソースに属します。ポートがオープンしている時にcall/ccで継続を捕まえたとして、ポートが一度閉じられてしまうと、その継続を再度呼び出してもポートは閉じられたままです。(dynamic-windを使って継続再起動時に閉じられたポートを再オープンして元の場所までseekする、といったことを書けないわけではありませんが、常に使えるとは限りません)。あるいは、データベースのトランザクションのように、後戻りできないことに意味があるケースもあります。

loadがこのように動作すべきかどうかというのは仕様では決められていません。with-input-from-portなどのファイル関数では、エラーで実行を中断した場合にはポートをクローズしますが、call/ccで脱出した場合は戻ってくる可能性を考えてポートは開いたままになります (継続が使われずにGCされると、ポートもクローズされます)。ただloadの場合、Gaucheではload全体をひとまとまりとみなす処理(autoprovideなど)があるので、トランザクションのように扱うのが都合が良かったのでこうしています。

これはcall/ccを使ったユーザレベルスレッドライブラリとは干渉してしまうかもしれません。何か不都合があるようでしたら変更を考えます。

投稿2015/10/17 20:45

shirok

総合スコア17

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

vc3000

2015/10/18 00:31

ありがとうございます。 「#<iport(closed) ./a.scm 0x2235240」が何を指すのかも分かっていなかったのですが、a.scmからプログラムを読み込むためのポートであり、loadが終わった時点でこのポートは閉じられていたという理解でよいでしょうか? そして「↓これをコメント解除する」をするとexit-contに保存される継続は「b.scmからプログラムを読み込むポート」を使うようになっているのでエラーは起きないと。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問