2005/4-2007/12まで
p.348の図9.1で、適当な時点を選ぶとエラーが発生して停止し図9.2のリストが得られません。エラーを解除して先に進む方法を教えてください。
- ご迷惑をおかけしました。おそらく書籍中で使用しているSqueakNihongo6固有の原因で起こったエラーです。日本語がソース上のコメントに含まれていると、このようなことがまれに起こります。とりあえず無視してp.349の変更を加えていってみてください。スナップショットを取った後の時点からは、正常に最近の変更を見ることができると思います。(umejava)
エラー解除の件有難うございました。実験科学教育用のわかりやすい指導書をつくる立場から、C/C++の相乗効果が期待できるsqueakに注目しています。Windows XP(Home ed.)環境下での質問です。P.380-381のpreambleファイルとpostscriptファイルの作り方及びそれらをinstallディレクトリに置く方法が見つかりません。添付のMole Attack.sarのように、zipを開いたとき、install/,install/preamble,install/postscriptのように表示できません。ご教示をお願いします。
- C/C++で計算処理、Squeakでインターフェースという棲み分けでしょうか。興味深い活用法ですね。さて、ご質問の件ですが、preambleとpostscriptファイルは通常のテキストファイルですので、どのような方法で作成されてもかまいません。ワークスペース上のコードをエディタにコピーペーストしても良いですし、Squeakからはファイルリストによって作成していくことができます。ファイルリストの場合、メニューを選ぶことで、"add new directory", "add new file"などの項目が出てきます。"accept"で保存できます。(umejava)
p.85 repeat の例でさいころの目のプログラムが載っていますが, [ ... ] repeat. の外側で,リターンされた count の値を Transcript show: で表示させることはできないのでしょうか? (F.Saito)
自己解決しましたので,上記質問の撤回をお願いいたします。↑count が [ ... ] repeat. の外側に脱出する,C 言語などの break のような働きをするのかと勘違いしていました。文字どおり return の動作をするようですね。失礼しました。 (F.Saito)
- breakに該当するような命令はSmalltalkにはありませんが、上級者になりますと、ブロックなどを作って似たようなものを作ることもできます。制御構造をも自分で作れるというのは、Smalltalkを使う上での大きな喜びですね。(umejava)
稚拙な書き込みにコメントして頂きまして恐縮です。一応12章のあたりまで読み進みましたが,理解不足なので最初にもどって読み直ししています。一度目の時はプログラム例を打ち込んで実行してみるだけで精一杯だったのですが,二度目だと自分なりに変更を加えたりできるようになりました。いつかちゃんとしたプログラムが作れたらいいのですが。 (F.Saito)
- Smalltalkは、使い込むうちに味の出てくるスルメのような言語です。ぜひオリジナルのプログラムを作って楽しんでみてください。(umejava)
『自由自在 Squeakプログラミング』を、実際にコードを書いて動かしながら、読み進んでおります。使っているSqueakは、Windows版 ver 3.8 です。
p173 の「5.1.3 ブロック内リターン」でつまずいています。
載っているとおりにコードを書いて doit すると、デバッガが起動されてしまいます。問題を単純化するために、下記のようなコードを書いてみました。
myblock := [ |sum|
sum := 0.
^sum.
].
myblock value
やはりデバッガが起動されます。デバッガのタイトルには、
BlockCannotReturn
と表示されています。何が悪いのか、自分にはよくわかりません。
よろしくお願いします。(TS)
- こんにちは。おそらくmyblock valueの箇所を複数回"do it"されているのだと思います。ブロックを定義したメソッド内でリターンが一度実行されると、2度とそのブロックはリターン不可能になります。(処理を終えてリターンしたブロックは抜け殻のようなものです)。上記のコードの場合、^sumの部分がなければ、myblock valueを何度でも実行できるようになります。(umejava)
umejavaさん、お返事(ご回答)ありがとうございます。
... おそらく、ご指摘のとおりだと思います。
↑このようにやや歯切れの悪い返事になりました理由は、下記のとおりです。
- myblock := [ ... ]. myblock value の2文を同時に選択&doit すると、
デバッガが起動することなく、期待通りに動作します。
- myblock := [ ... ] と myblock value の各文を別々に、
順に doit すると、2度目の myblock value に対する doit で
デバッガが起動してしまいます。
このような現象になってしまう理由/原因をお教えいただければ幸いです。
よろしくお願いします。(TS)
- ご指摘の件ですが、ようやく問題とされているところがわかりました。2回実行などと勘違いしてしまい、すみません。以下、多少難しくなるかもしれませんが、おつきあいください。原因はワークスペースで"do it"しているということ自身にあります。Squeakなど、クラシックなSmalltalkの実装では、"do it"を「一時的にDoItというインスタンスメソッドをUndefinedObjectに定義して、メッセージ送信する」という方式で実現しています。このやり方は、何でもメッセージ送信で実現するという、いかにもSmalltalkらしい実装方法なのですが、ときに問題を起こす場合もあります。今回の例がまさにそれに該当します。1文目の"do it"で存在したはずの、myblockのホームコンテキスト(ブロックが生まれた故郷となるメソッド - 今回はUndefinedObject>>DoIt)が、2文目の"myblock value"を"do it"するときには上書きされてしまい、なくなってしまっているのです。このため、ブロックのコンテキスト情報が破綻してしまい、BlockCannotReturnの例外が発生することになります。(umejava)
umejavaさん、丁寧な解説を本当にありがとうございます。
だいたい(半分くらいは)理解できました。
それにしても、流石、深い深いところまでご存知なのですね。すごいなぁ。
念のため、ブロックの挙動に対する自分の認識が正しいか否か確認するため、
下記のコードをまとめて do it してみました。
myBlock _ [ Transcript cr; show: 'hello' ].
myBlock value.
myBlock value.
... ちゃんと2回評価されて、2行の hello が表示されますね。
そして、以下のコードをまとめて do it すると、
nestedBlock _ [ |sum|
Transcript cr; show: '### START ###'.
sum _ 0.
10000 timesRepeat: [
sum _ sum + 1.
sum > 100 ifTrue: [ ^sum ].
Transcript space; show: sum.
].
Transcript cr; show: '### END ###'.
].
nestedBlock value.
nestedBlock value.
... 2度目の value 送信では、何も起きません。
これが、umejavaさんがおっしゃっている「抜け殻状態のブロック」って
ことなんですね。
ブロックを書く場合に、きをつけておかないといけませんね。
ありがとうございました。m(_ _)m
- 上記の例の場合は、実は2度目のnestedBlock valueは実行されていません。最初のvalueを送って^sumが実行された時点で、全体の処理を抜けてしまうからですね。2度目のnestedBlock valueをself haltなど書き換えてみると、決してhaltしないことがわかります。抜け殻になったブロックについては、より正確にいうと、「ブロックを定義したメソッドコンテキストが、既に失われてしまったブロック」ということになります。例えば、適当なクラス(BlockTester)に以下のようなメソッドを定義します。
BlockTester >> test1
[^1] fork.
^2
- BlockTester new test1として"print it"すると、2が返ってきますが、即座にBlockCannotReturnの例外が起こります。これは、2を返してtest1の実行が既に終わっている(test1のメソッドコンテキストが消失した)にもかかわらず、forkで作られた別スレッドが、同じメソッドコンテキストから再び1をリターンしようとするからです。
- まとめますと、以下のようになります。
- ブロック内での^は、ブロックからではなくそのブロックを定義したメソッドコンテキストからリターンする
- 同じメソッドコンテキストから2回以上はリターンできない
- 「ブロックを制するものはSmalltalkを制する」と呼ばれます。これからもがんばってください。(umejava)
P.42 に、Pen example の実行結果が図 1.17 として載っています。do it してみると、Workspace のエリアには描画されない、或は Workspace で上書きされてしまうようです。図のように完全な図形を表示する方法があるのでしょうか? (F.Saito)
- キーボードショートカットによる起動(Alt+d)をお試しください。メニューから"do it"すると、実行直後にワークスペースの再描画が起こり、上書きとなってしまうようです。(umejava)
(Alt+d)でできました。いつもつまらない質問にお答えいただきまして、ありがとうございます。(F.Saito)
- いえいえ、わたしこそいつもショートカットばかり使ってしまうもので、マウス操作による考慮が欠けていました。ご指摘ありがとうございます。(umejava)
Debian GNU/Linux 4.0 Etch に Sqeqk をインストールしてみましたが,save as で名前を入力中に以下のようなメッセージとともに終了してしまいます.
Segmentation fault
2027132628 ProcessorScheduler class>idleProcess
2026612936 [] in ProcessorScheduler class>startUp
2026613028 [] in BlockContext>newProcess
アボートしました
以上,一応ご報告します.Debian 自体の問題かとも思えるし,ご意見箱の趣旨にそわない内容かもしれないのでこの書き込みは削除していただいてもかまいません.(F.Saito)
初歩的な質問で恐縮ですが、「P.192」で、オブジェクト「myDictionary」にyourselfメソッドを送信しない場合と送信した場合のふるまいの違いが理解できません。yourselfメソッドを送信した場合、atメソッドをつないだ結果が有効となるのでしょうか。(Takagi)
- Objectクラスのyourselfの中身を見ても何も書かれていません。つまりメソッドのデフォルトの戻り値であるselfが返ることになります。例えば以下のような場合に使います。
- 例としてCounterクラスにincrementというメソッドがあるとします。
Counter>> increment
^count := count + 1
- このメソッドは、現在のcount値を返しています。これは妥当な戻り値のようにも思えますが、以下のようにincrementを送ったときにはむしろ戻り値が邪魔になります。
myCounter := Counter new increment; increment; increment.
- 上記の場合counterには3が代入されることになります。本当は(countが3に増えた)Counterのインスタンス自身を代入したかったのにincrementの戻り値が数値になっているからです。このようなときに最後にyourselfを送るとどうなるでしょうか。
myCounter := Counter new increment; increment; increment; yourself.
- myCounterにはCounterのインスタンスが無事に入ります。yourselfを送ると、そのメソッドの中身はselfを返すように書いてあるからです。
- Dictionaryのat:put:の場合は引数を返すようになっています。
at: key put: anObject
(略)
^anObject
- 従って、最後にyourselfを送信しないとmyDictionaryには、本文で最後にat:put:した'トゲトゲ'が代入されることになります。(ご質問には「myDictionaryにyourselfメソッドを送信しない場合と送信した場合」とありますが、myDictionaryにはyourselfメッセージは送信されていません。連続したメッセージ送信の結果、最後の戻り値がmyDictionaryに代入されるのです。この辺りが不明な場合は、「2.7.5 優先順位の組み合わせ」をもう一度じっくりと読まれた方が良いかもしれません)。(umejava)
Link to this Page
- ご意見箱 last edited on 30 September 2021 at 2:21:41 pm by 122x220x71x163.ap122.ftth.ucom.ne.jp