K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[428] Re:クラスメソッドとクラス変数
投稿者:タイガー
2007/02/20 02:13:25

>これはまずいのでは。たとえば「コレクション中に同じ要素がないかどうか」を >二重ループでチェックするような場合、コレクションそのものが位置を保持していると >ひとつしか持てないので困ります。 確かにその通りですね。良くない設計ですね。 結局、外部Iteratorしかなさそうですね...。 ところでこれって、(ぱ)さんの言われているマルチプルインスタンスの問題ですか? >方法2. Iteratorクラスを作る。ArrayクラスとLinkedクラスの区別は、 > Iteratorクラスの中に隠す。 > compare()に、Iteratorのインスタンスを渡す。 あと方法2ですが、よく考えてみたらArrayとLinkedの区別をIteratorクラスに隠す のは良くないですね。if~elseが出てくるので。 ArrayIteratorとLinkedIteratorの両方を用意して、利用者側(クライアント側)が それを使うしかないですね。クラスの生成部分を抽象化したければJavaみたいに Factoryで隠せば良いですので。 今回色々勉強になりました。ありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[427] Re:オブジェクトとクロージャ
投稿者:(ぱ)
2007/02/20 02:13:25

>はじめまして。 はじめまして... と言いつつ、TRIPLEさんのblogは少し前から読んでました。 「プログラミング言語を作る」でGoogleしたらひっかかりましたので (^^; # 書いた方としては反応が気になるわけです。やっぱり。 >"JavaScriptの実装に似ている" >という印象を受けましたが、"Hawksさん"のサイトも参考にされていたのですね。 です。あのページにはお世話になりました。 こういう、どちらかというとマイナーな機能をcrowbarに組み込むのは、 企画の趣旨的にどうかとも思いましたが(どうせ言語の作り方を説明するなら、 対象読者がいつも使ってる言語の方が目的が絞れるように思うので)、 Hawksさんのページを含め、JavaScriptについていろいろ調べてたら、 「うおお、これは作ってみたい」と思ったのでこうなりました。 それでは今後ともよろしくお願いいたします。
[この投稿を含むスレッドを表示] [この投稿を削除]
[426] Re:クラスメソッドとクラス変数
投稿者:(ぱ)
2007/02/20 02:13:25

私は常々Javaとかで外部イテレータを使うたび、「めんどくせー」と思ってました。 なので、Ruby式のイテレータいいじゃん、と思っていましたが、 確かにkitさんのおっしゃるようなケースで困りますね。 (Javaのように)コレクションがIteratorを返すようになっていれば、 ライブラリ関数のforeachとクロージャで、C#のforeachみたいなものは作れるから、 その方面でいくのがよさそうですね。 >方法1. ArrayとLinkedの両方に共通なメソッドで、各要素を先頭から順に > 取り出せる関数(インターフェース)を定義する。 これはまずいのでは。たとえば「コレクション中に同じ要素がないかどうか」を 二重ループでチェックするような場合、コレクションそのものが位置を保持していると ひとつしか持てないので困ります。 コレクションにeachメソッドを付けるやり方では、位置を押さえているのは eachメソッドのローカル変数なので問題にならないですけど。
[この投稿を含むスレッドを表示] [この投稿を削除]
[425] Re:クラスメソッドとクラス変数
投稿者:タイガー
2007/02/20 02:13:25

Rubyで、kitさんのcompare()メソッドを実装するにはどうすれば実現可能か考えてみました。 まず、Array(配列を表す)クラスの他にLinked(リンクリストを表す)クラスが あると過程して、この2つのクラス両方がcompare()に区別なく渡せるような実装を考えます。 方法1. ArrayとLinkedの両方に共通なメソッドで、各要素を先頭から順に 取り出せる関数(インターフェース)を定義する。 つまり、next()、isDone()、currentItem()を両方のクラスに実装する。 compare()に、ArrayやLinkedのインスタンスを渡し、 このメソッドを使って実装する。 方法2. Iteratorクラスを作る。ArrayクラスとLinkedクラスの区別は、 Iteratorクラスの中に隠す。 compare()に、Iteratorのインスタンスを渡す。 方法3. Linkedにも(Arrayクラスの様な)to_aメソッドを実装し、 to_aで、全要素を配列にして1つずつ比較。 私はあまりRubyに精通していないので、以上の単純な方法を考えました。 まず、方法3ですが、実現はできてもcompare()の実装の「ロジック」が ストレートな表現ではないため、良い方法とは思えません。同様に 特殊なことで実現できたとしても同じ意味で良くないです。 方法1は、「データ構造」クラスの中に(2つのクラスに共通な、つまり抽象的な) データのアクセサをつけることで実現します。 方法2は、kitさんと同様にIteratorクラスで表現する方法です。 方法1と方法2の比較ですが、どちらが良いのかは難しいですが、 Arrayクラスをあまりよごしたくないので、直感的にはIteratorクラスを 作成する方が良いように思えます。 >しかし、記述力というか、制御構造の自由度という点では >ArrayIterator 的なやり方の方が優れていますから、もしもどちらか その通りかもしれません。 >実際のところは、たいていの言語のコレクションライブラリが、each >メソッド式と、ArrayIterator 的方法の両方の機能を提供しているよ >うな気がします。 RubyはIteratorクラスがありません。observer(Observableモジュールを使う) とかはあるみたいなので、Iteratorも標準で入れて欲しいです。 >この場合、ArrayIterator() 式を外部 Iterator、each メソッド式を >内部 Iterator と呼んで区別するようです。 結局、データ構造のクラスの中に入れるか、別のクラスにするかという 感じでしょうか。 私もIteratorと言うと外部の方が思い浮かびます。Javaのイメージで。 crowbarは、Rubyのイメージだったので内部の方の実装をイメージしてました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[424] Re:クラスメソッドとクラス変数
投稿者:kit
2007/02/20 02:13:25

> GoF のデザインパターンをはじめ、Iterator という名称を用いた > 時には、ArrayIterator() が生成するような、繰り返し用のオブジェ > クトを指すことの方が多いんじゃないでしょうか。 念のため確認してみたんですが、GoF の場合、クラス図では ArrayIterator() 式のやり方しか記載してないんですが、 文章の方では、ruby の each メソッド式のやり方も紹介してました。 この場合、ArrayIterator() 式を外部 Iterator、each メソッド式を 内部 Iterator と呼んで区別するようです。 読んだのははるか昔なので、さっぱり忘れてました。 失礼しました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[423] Re:クラスメソッドとクラス変数
投稿者:kit
2007/02/20 02:13:25

> 利用者側がclosureを作るのが面倒というのは、 : > iterate()というメソッドの中にループ処理を隠している分、 > Iteratorを使うよりも記述はシンプルだと思います。 確かに、「面倒」というのは、あまり適切じゃない形容詞でしたね。 each メソッドのような方法は、できる能力が限られている分、むし ろArrayIterator 的なやり方よりも短い表現で済むのが (crowbar を 含めて) 普通だと思います。 > Iteratorのご紹介ありがとうございます。ただIteratorは良い方法 > だと思いますが、Array自身にeachメソッドを付ける方法とどちら > が良いかはよく分かりません。 誤解を与えて申し訳ないです。Ruby でいう each メソッドのような 方法が悪いと言ってるわけではありません。each メソッド式のやり 方で十分な場合は、記述が短いという点で優れているわけですから、 そちらを使った方がいいことの方が多いでしょう。 しかし、記述力というか、制御構造の自由度という点では ArrayIterator 的なやり方の方が優れていますから、もしもどちらか 片方だけしか提供しないから選べと言われたら、ArrayIterator 的方 法がいいんじゃないでしょうか。 実際のところは、たいていの言語のコレクションライブラリが、each メソッド式と、ArrayIterator 的方法の両方の機能を提供しているよ うな気がします。 ただ、Iterator という言い方をした時に、each メソッドのような 方法が最初に出てくることには若干違和感があります。 GoF のデザインパターンをはじめ、Iterator という名称を用いた時 には、ArrayIterator() が生成するような、繰り返し用のオブジェク トを指すことの方が多いんじゃないでしょうか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[422] オブジェクトとクロージャ
投稿者:TRIPLE
2007/02/20 02:13:25

はじめまして。 "プログラミング言語を作る"の"オブジェクトとクロージャ"の実装を見て "JavaScriptの実装に似ている" という印象を受けましたが、"Hawksさん"のサイトも参考にされていたのですね。 私もJavaScriptの変数のスコープや配列の機能、"functionの使い方"で悩んでいたときに、"Hawks"のサイトをみて疑問が解消されましたし。 JavaScriptは"小技集"みたいなサイトはたくさんあるのですが、"言語仕様"をわかりやすく解説したサイトはあまりなく、とても重宝しています。 そういえば、JavaScriptも型のない言語なのですが、他の人が書いたソースをデバックしているときキレそうになったことがあります。 その人が書いたソース、コメントが何一つなく、関数の引数に何を渡しているのかさっぱりわかりませんでしたから。 その時、"Javaの謎+落とし穴"の"Javaにgenericがないのは欠陥だ"という意味が実感できたような気がしますが(笑)
[この投稿を含むスレッドを表示] [この投稿を削除]
[421] Re:クラスメソッドとクラス変数
投稿者:タイガー
2007/02/20 02:13:25

>えーと、iterator は、iterator 自体がオブジェクトであるような >作りにした方が便利だと思います。iterator を利用する側が >必ず closure を作るのは面倒くさいですし、なにより、 利用者側がclosureを作るのが面倒というのは、Ruby風の a1.iterate() { |i| print("" + i + " "); } という書き方ができないからであって、iterate()というメソッドの 中にループ処理を隠している分、Iteratorを使うよりも 記述はシンプルだと思います。 ただ逆に、慣れてないとループしているというのが分かりづらくなっています。 >複数のコレクションを、複数の iterator を使って同時に並行して >アクセスするようなプログラム、たとえばコレクションどうしの >大小比較: >function compare(i, j) { ... >} >print(compare(ArrayIterator(a), ArrayIterator(b)) + "\n"); >みたいなことをしようとすると、eachメソッド方式では困っちゃいます。 Iteratorのご紹介ありがとうございます。ただIteratorは良い方法だと思いますが、 Array自身にeachメソッドを付ける方法とどちらが良いかはよく分かりません。 Arrayみたいな「データ構造」を表すクラス(もどき)にリスト(の要素)をイテレートするという 「処理」を表すメソッドを持たせるのは、真面目に考えればよくないのかもしれませんが、 頻繁にでてくる処理なので、Arrayに持たせるのはバランス的に自然なのかもしれません。 ただ、compare()みたいなのをどう表現するのかは、調べてみます。 (ぱ)さんへ >ひとつのクラスのconstructorで10個のpointが作られた時、 >「クラスフィールド」はひとつしかないので、ただのインスタンス変数とは違うでしょう。 よく考えたらその通りでした。すいません。 closureの特性をうまく利用した方法だと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[420] Re:クラスメソッドとクラス変数
投稿者:(ぱ)
2007/02/20 02:13:25

取り急ぎ。 >で、コンパイルしてみると、 >1. 単項の「!」演算子がない。(これは欲しいです) >2. C言語の「,」演算子がないので、for 文の3番目の項の > 「i.next(), j.next()」でエラー ... >実行すると > 33:面面面面民藥算劼boolean型には使えません。 >となります。これはなぜでしょうね。 これは、エラーメッセージ生成部分がバグっているようで、本来は 「33:==はboolean型には使えません。」 と出るべきものです(メッセージの可変部が先頭にあるとだめらしい)。 で、==がなぜbooleanに使えないかというと、単に実装してないためです(^^; eval.cのeval_binary_booleanにelse ifを書き足すだけのはずですが、 すみません忘れてました。 http://kmaebashi.com/programmer/devlang/crowbar_src_0_3/S/10.html#280 booleanの比較なんてそうそうするもんじゃない、という考え方もありますが、 その上単項の!もないのではどないせいっちゅうんだ、という話ですね。 いろいろ仕様のポカ、テスト漏れがありましてすみません。次バージョンで直します。 報告ありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[419] Re:クラスメソッドとクラス変数
投稿者:kit
2007/02/20 02:13:25

いろいろ訂正… > で、コンパイルしてみると、 「コンパイルしてみる」じゃなくて「実行してみる」ですね。(^^;) コンパイラ言語ばかり使っている癖でつい… > this.next = closure() { this.index = this.index++; }; ここは編集間違いで this.next = closure() { this.index++; }; でした。 あと、this.theArray と this.index をユーザに公開するのは 良くないので、ArrayIterator() の実装は function ArrayIterator(anArray) { this = new_object(); index = 0; this.first = closure() { index = 0; }; this.next = closure() { index++; }; this.isDone = closure() { return index >= anArray.size(); }; this.currentItem = closure() { return anArray[index]; }; return this; } とした方がいいですね。 > 実行すると > 33:面面面面民藥算劼boolean型には使えません。 > となります。これはなぜでしょうね。 これは調べてません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[418] Re:クラスメソッドとクラス変数
投稿者:kit
2007/02/20 02:13:25

> と、ここまで書いて、実際に動作するプログラムかどうか試そうとしたら、 > 文法エラーになっちゃいました。 実装をちらっと見たら、すぐ原因が分かりました。 最新版である crowbar 0.3 ではなくて、crowbar 0.1.01 を使っていた のが原因でした。(大汗;;;) 大変失礼しました。 http://kmaebashi.com/programmer/devlang/index.html のページに、最新版への配布ページへのリンクがあると、 多少はこういう間違いが減るかもしれません… で、コンパイルしてみると、 1. 単項の「!」演算子がない。(これは欲しいです) 2. C言語の「,」演算子がないので、for 文の3番目の項の 「i.next(), j.next()」でエラー 3. closure() への代入文で「;」を忘れていた といった問題がありました。 直してみたものが以下の通りなんですが、 実行すると 33:面面面面民藥算劼boolean型には使えません。 となります。これはなぜでしょうね。 function ArrayIterator(anArray) { this = new_object(); this.theArray = anArray; this.index = 0; this.first = closure() { this.index = 0; }; this.next = closure() { this.index = this.index++; }; this.isDone = closure() { return this.index >= this.theArray.size(); }; this.currentItem = closure() { return this.theArray[this.index]; }; return this; } function compare(i, j) { while (i.isDone() == false && j.isDone() == false) { if (i.currentItem() < j.currentItem()) { return -1; } if (i.currentItem() > j.currentItem()) { return 1; } i.next(); j.next(); } if (i.isDone() && j.isdone()) { return 0; } if (i.isDone()) { return -1; } else { return 1; } } a = {1, 2, 3, 4, 5, 6, 7, 8}; for (i = ArrayIterator(a); i.isDone() == false; i.next()) { print("" + i.currentItem(), " "); } print("\n");
[この投稿を含むスレッドを表示] [この投稿を削除]
[417] Re:クラスメソッドとクラス変数
投稿者:kit
2007/02/20 02:13:25

> >あと、制御構造の抽象化としてiteratorのようなものを表現する場合、 > >Ruby(のeachメソッド)みたいにクロージャをメソッドに渡す形でサンプルを > >書いてみたのですが、 > >もっとうまいやり方がありますか? > これでよいのではないでしょうか。 えーと、iterator は、iterator 自体がオブジェクトであるような 作りにした方が便利だと思います。iterator を利用する側が 必ず closure を作るのは面倒くさいですし、なにより、 複数のコレクションを、複数の iterator を使って同時に並行して アクセスするようなプログラム、たとえばコレクションどうしの 大小比較: function compare(i, j) { for (; !i.isDone() && !j.isDone(); i.next(), j.next()) { if (i.currentItem() < j.currentItem()) return -1; if (i.currentItem() > j.currentItem()) return 1; } if (i.isDone() && j.isdone()) return 0; if (i.isDone()) return -1; else return 1; } print(compare(ArrayIterator(a), ArrayIterator(b)) + "\n"); みたいなことをしようとすると、eachメソッド方式では困っちゃいます。 なので、たぶん次のような設計の方がいいと思います。 function ArrayIterator(anArray) { this = new_object(); this.theArray = anArray; this.index = 0; this.first = closure() { this.index = 0; } this.next = closure() { this.index++; } this.isDone = closure() { return this.index >= this.theArray.size(); } this.currentItem() = closure() { return this.theArray[this.index]; } return this; } と、ここまで書いて、実際に動作するプログラムかどうか試そうとしたら、 文法エラーになっちゃいました。UNIX版をコンパイルしてみたんですが、 次のような1行だけのプログラムで a = {1,2}; 1:文法エラー({付近) となります。 また、次のような2行だけのプログラムでも a = new_object(); a.hoge = 1; 2:不正な文字(.) となります。 crowbarの実装の中身は全然見てないんですが、UNIX版だけの問題なんでしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[416] Re:クラスメソッドとクラス変数
投稿者:(ぱ)
2007/02/20 02:13:25

>>うーん、私が狙ったのは、複数のpointオブジェクトから共通に参照できる >>ひとつのクラスフィールド、です。 ... >それだとprivateなインスタンス変数な気がします...。間違ってたらすいません。 ひとつのクラスのconstructorで10個のpointが作られた時、 「クラスフィールド」はひとつしかないので、ただのインスタンス変数とは違うでしょう。 >あと、制御構造の抽象化としてiteratorのようなものを表現する場合、 >Ruby(のeachメソッド)みたいにクロージャをメソッドに渡す形でサンプルを >書いてみたのですが、 >もっとうまいやり方がありますか? これでよいのではないでしょうか。私もやるとすればこういう形だと思っていました。 >あと、C#のforeachやJava5の拡張forのようなものを実装する予定はありますか? 予定は未定ですが、文法としてそういうものを実装するつもりはありません。 言語仕様がライブラリに依存するのはあまり美しくないと思っていますので。
[この投稿を含むスレッドを表示] [この投稿を削除]
[415] Re:クラスメソッドとクラス変数
投稿者:タイガー
2007/02/20 02:13:25

>うーん、私が狙ったのは、複数のpointオブジェクトから共通に参照できる >ひとつのクラスフィールド、です。 >まあ、create_point_class()を複数回呼んでしまえば複数作れてしまいますが、 >それは利用者側の問題にしてよいのではないかと。 それだとprivateなインスタンス変数な気がします...。間違ってたらすいません。 但し、パフォーマンスはともかく、利用者側から見れば、 やりたいことは実現できますので現時点では十分かもしれません。 >あくまで「静的な」(ひとつしかない)データが、グローバル変数以外の方法で必要だ、 >ということであれば、Cのstatic指定したローカル変数のようなものを付けると >いうのはひとつの手かもしれませんが。 staticのローカル変数でも実現可能ですね。どう設計するかですね。 あと、制御構造の抽象化としてiteratorのようなものを表現する場合、 Ruby(のeachメソッド)みたいにクロージャをメソッドに渡す形でサンプルを書いてみたのですが、 もっとうまいやり方がありますか? あと、C#のforeachやJava5の拡張forのようなものを実装する予定はありますか? function Array(arr_data) { this = new_object(); this.arr_data = arr_data; this.iterate = closure(c) { for (i = 0; i < this.arr_data.size(); i = i + 1) { c(this.arr_data[i]); } }; return this; } a = {1, 2, 3, 4, 5, 6, 7, 8}; c1 = closure(i) { print("" + i + " "); }; a1 = Array(a); a1.iterate(c1);
[この投稿を含むスレッドを表示] [この投稿を削除]
[414] Re:synchronizedメソッドの“変なこと”
投稿者:本多
2007/02/20 02:13:25

>>ずいぶん昔、私もマルチスレッドではないのですが、複数のCPUで一つのデバイスに >>アクセスするようなプログラムではまったことがあって、その原因はこんな行でした。 >> x |= y; >なんかモロにマルチスレッドのように思うんですが… (^^; 全く異なる複数のCPU上で動作する2つのプロセスが同じリソースにアクセスする様なものも「マルチスレッド」と言うのかどうか、ちとわからんのですが、 >でも、組み込みなどだとまた事情が違いそうですね。 組み込みの癖に複数のCPUがあるなんていう贅沢な組み込み環境なのですが、複数のCPUがあるくせに排他制御や割り込みをあげるハードウエアがプア...というか、存在しなくて(CPUは汎用品だけど、CPU間をつなぐ部分が社内製だった)、しかたなく同時にアクセスできるメモリにフラグを立てる形で実現していたとかいう状況だったりします。 で、フラグが何種類か必要なので、ビット対応にした(だからORしてる)というなんとも間抜けな設計でスタートしていて。 そもそも通信をガシガシやる部分だったので「ほとんどの情報は共有されてる」ために「複数のスレッドで共有するオブジェクトを限定する」っていうのは意味がなくて「入り口に管理用のオブジェクトを置くとかしてちゃんと管理する」のまさに管理用のオブジェクトが、こんなのだったんですね。あのころは若かったと言い訳して...(^^;)
[この投稿を含むスレッドを表示] [この投稿を削除]
[413] Re:synchronizedメソッドの“変なこと”
投稿者:(ぱ)
2007/02/20 02:13:25

>ずいぶん昔、私もマルチスレッドではないのですが、複数のCPUで一つのデバイスに >アクセスするようなプログラムではまったことがあって、その原因はこんな行でした。 > > x |= y; なんかモロにマルチスレッドのように思うんですが… (^^; これぐらいミクロなレベルでバグを入れてしまうと、もうたいていはデバッグどころか 再現するのも不可能でどうしようもなくなりますから、Webアプリケーションなんかでは、 ・そもそも複数のスレッドで共有するオブジェクトを限定する。 ・それでも共有するオブジェクトは、入り口に管理用のオブジェクトを  置くとかしてちゃんと管理する。 ってことだと私は思っています。 でも、組み込みなどだとまた事情が違いそうですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[412] Re:クラスメソッドとクラス変数
投稿者:(ぱ)
2007/02/20 02:13:25

>ソースの5行目は、 >this.constructor = closure() { >でなく、 >class.constructor = closure() { >だと思います。 です。すみません間違えました。 あと、「closure(x, y) {」のように引数が必要ですね。 >上のコードでは、new_object()でオブジェクトを作成しないと >「#このへん」の変数を参照できないと思いますので、 >結局インスタンス変数に見えるような気がします。 うーん、私が狙ったのは、複数のpointオブジェクトから共通に参照できる ひとつのクラスフィールド、です。 まあ、create_point_class()を複数回呼んでしまえば複数作れてしまいますが、 それは利用者側の問題にしてよいのではないかと。 あくまで「静的な」(ひとつしかない)データが、グローバル変数以外の方法で必要だ、 ということであれば、Cのstatic指定したローカル変数のようなものを付けると いうのはひとつの手かもしれませんが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[411] Re:クラスメソッドとクラス変数
投稿者:タイガー
2007/02/20 02:13:25

こんにちは。 >「今の(crowbarの)仕様」ということだと、そもそもクラスがないのに、 >クラスメソッド、クラス変数とは何ぞや? という話になるかと思いますが、 確かにその通りですね。クラス「らしきもの」ですね。 >function create_point_class() { > class = new_object(); > # このへん > > this.constructor = closure() { > this = new_object(); > this.x = x; > this.y = y; > > this.print = closure() { > print("(" + this.x + ", " + this.y + ")\n"); > }; > … > return this; > }; > return class; >} > >とか書けばできそうに思うのですが、どうでしょうか(すみません試してないです)。 >「#このへん」で作ったローカル変数や、ローカル変数に代入したクロージャは、 >コンストラクタの中で定義されているメソッドからだけ参照できるはずです。 ソースの5行目は、 this.constructor = closure() { でなく、 class.constructor = closure() { だと思います。 上のコードで名前空間らしきものが表現できているように思いますが、 私の考えていたのは、オブジェクトを作らないでグローバルと名前空間が違う、 でも静的な寿命を持つ変数が使えるかを考えていました。 上のコードでは、new_object()でオブジェクトを作成しないと 「#このへん」の変数を参照できないと思いますので、 結局インスタンス変数に見えるような気がします。 >私としては、クラス変数やクラスメソッドというものに、わざわざ言語仕様で >対応するだけの価値を感じていません。 >crowbarにはそもそもクラスがないですが、クラスベースのOO言語を作るとしても、 >クラス変数やクラスメソッドはつけず、グローバル変数のようなものにして、 >名前空間を選択的に開示できるような形にすると思います。 たぶんその辺は言語の特徴になってくると思いますので、クラス変数らしきものを どう表現するのか(あるいはしないのか)は難しいかもしれません。 ただ、Javaとかに慣れているとクラス変数はストレートで分かりやすい気がします。
[この投稿を含むスレッドを表示] [この投稿を削除]
[410] Re:synchronizedメソッドの“変なこと”
投稿者:本多
2007/02/20 02:13:25

>◎getとsetが分かれていたり… ~中略~ >ふたつのスレッドA, Bが以下のようにxをインクリメントしようとすると、 > x = p.getX(); // スレッドA ←(1) > x = p.getX(); // スレッドB ←(2) > p.setX(x+1); // スレッドA ←(3) > p.setX(x+1); // スレッドB ←(4) ~中略~ >結局、マルチスレッドで正しくプログラムを動かしたいのであれば、 >Pointのような低レベルなクラスで、個々のメソッドに機械的にsynchronizedを >つけても意味がなく、アプリケーションのレベルで対処しなければなりません。 ~中略~ >あんまり理解されてないことなんですかねえ。 こういうのって、マルチスレッド プログラムで再現性の低いバグで悩んだ経験がないとなかなか思いつかないことかもしれませんね。 ずいぶん昔、私もマルチスレッドではないのですが、複数のCPUで一つのデバイスにアクセスするようなプログラムではまったことがあって、その原因はこんな行でした。 x |= y; xの値をCPUレジスタに読み出して、その値にyの値を加えたものを、xに書き込む...前に別のCPUからxに書き込みがあったんです。 このときは高い確率で再現できるプログラムが偶然用意できたのが幸いでしたが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[409] Re:クラスメソッドとクラス変数
投稿者:(ぱ)
2007/02/20 02:13:25

>「プログラミング言語を作る」をいつも楽しみにしています。 ありがとうございます。 >クラスメソッドとクラス変数は、今の仕様で実現は可能ですか? 「今の(crowbarの)仕様」ということだと、そもそもクラスがないのに、 クラスメソッド、クラス変数とは何ぞや? という話になるかと思いますが、 現在、create_point()のような関数を作ることでクラスじみたことを 実現しているように、何とか似たことを実現したい、ということであれば、 「クラスもまたオブジェクトである」 「インスタンスは、クラスのconstructorメソッドで生成する」 ということにして、 function create_point_class() { class = new_object(); # このへん this.constructor = closure() { this = new_object(); this.x = x; this.y = y; this.print = closure() { print("(" + this.x + ", " + this.y + ")\n"); }; … return this; }; return class; } とか書けばできそうに思うのですが、どうでしょうか(すみません試してないです)。 「#このへん」で作ったローカル変数や、ローカル変数に代入したクロージャは、 コンストラクタの中で定義されているメソッドからだけ参照できるはずです。 >また、実現不可能な場合、追加の仕様としてはどういうのを考えていますか? >グローバル変数で代用するのはちょっと…と思います。 私としては、クラス変数やクラスメソッドというものに、わざわざ言語仕様で 対応するだけの価値を感じていません。 crowbarにはそもそもクラスがないですが、クラスベースのOO言語を作るとしても、 クラス変数やクラスメソッドはつけず、グローバル変数のようなものにして、 名前空間を選択的に開示できるような形にすると思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[408] クラスメソッドとクラス変数
投稿者:タイガー
2007/02/20 02:13:25

こんにちは。 「プログラミング言語を作る」をいつも楽しみにしています。 個人的には、オブジェクトとクロージャ辺りからだんだん面白くなってきたと思います。 まだ機能的に色々追加していくのだと思いますが、クラスメソッドとクラス変数は、今の仕様で実現は可能ですか?色々考えたのですが、思いつきません。 また、実現不可能な場合、追加の仕様としてはどういうのを考えていますか? グローバル変数で代用するのはちょっと…と思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[407] Re:synchronizedメソッドの“変なこと”
投稿者:(ぱ)
2007/02/20 02:13:25

>こんにちは。はじめまして。 はじめまして。書き込みありがとうございます。 >もしよろしければ、可能性として起こりうる"変なこと"をご教示願えませんでしょうか? >getとsetが分かれていたり、setのXとYが分かれていたりしていたのでは、 というのが一応ヒントというか根拠のつもりです。 簡単な方から。 ◎setのXとYが分かれていたりしていたのでは… 現在(100, 100)であるPointを、(200, 200)に移動させたかったとしましょう。 そのために、 p.setX(200); p.setY(200); と書くと、setX()してからsetY()するまでの間、一時的に(200, 100)という状態になり、 この状態が他スレッドから見えてしまいます。 ◎getとsetが分かれていたり… ふたつのスレッドA, Bが以下のようにxをインクリメントしようとすると、 x = p.getX(); // スレッドA ←(1) x = p.getX(); // スレッドB ←(2) p.setX(x+1); // スレッドA ←(3) p.setX(x+1); // スレッドB ←(4) (3)でスレッドAがインクリメントした結果が(4)で上書きされてしまい、 ふたつのスレッドがひとつずつインクリメントしているはずなのに、 結局xは1しか増えないことになります。 ひとつめの問題は仕様だと言い張ることも可能かもしれませんが、 ふたつめの問題はおそらく致命的でしょう。 結局、マルチスレッドで正しくプログラムを動かしたいのであれば、 Pointのような低レベルなクラスで、個々のメソッドに機械的にsynchronizedを つけても意味がなく、アプリケーションのレベルで対処しなければなりません。 この手の問題は標準のクラスライブラリにもあって、古いコレクションクラス (Vectorなど)は、メソッドごとにちまちまとsynchronizedを付けていますが、 現実問題としてこれは無意味であり、後継のArrayListなどでは外されたわけです。 // ループが回っている間に別スレッドでremove()とかされると例外が発生する size = v.size(); for (int i = 0; i < size; i++) { Object o = v.get(i); } でも今Googleしてみたら、「シングルスレッドでよいときは効率向上のために ArrayListを使い、スレッドセーフにしたければVectorを使うべし」と解説している ページの多いこと… あんまり理解されてないことなんですかねえ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[406] synchronizedメソッドの"変なこと"
投稿者:sgi
2007/02/20 02:13:25

こんにちは。はじめまして。 楽しく拝読させて頂いております。 「オブジェクト指向再入門/なぜわからなくなってしまうのか?」の中の記述に判らないところがありましたのでご質問させてください。 ~引用ここから~ ところで「Javaの格言」という本では、 Pointのx, yをprivateにするメリットとして、マルチスレッド時の排他制御を挙げています。しかし、getX(), getY(), setX(), setY() を作ってそれぞれをsynchronizedにしたところで、この仕様ではマルチスレッドには対応できません。ちょっと考えてみればわかるように、 getとsetが分かれていたり、setのXとYが分かれていたりしていたのでは、複数のスレッドで実行されたら結局変なことが起きます。 ~引用ここまで~ synchronizedメソッドをコールすると、コールしたスレッドがインスタンス(メソッドのレシーバ)のモニタを取得するために、別スレッドが当該インスタンスのsynchronizedメソッドを呼び出しても安全(スレッドセーフ)であると認識しております。 上記の引用のなかの"変なこと"というのが、私の認識であるところの"スレッドセーフ"でないことを指すのか、または別のことを指すのか判りませんでした。 もしよろしければ、可能性として起こりうる"変なこと"をご教示願えませんでしょうか? よろしくお願いします。
[この投稿を含むスレッドを表示] [この投稿を削除]
[405] Re:ページ移動の通知
投稿者:(ぱ)
2007/02/20 02:13:25

はじめまして。 >前橋さんのリンク先にある >「中野康明の雑学ペ-ジ(2003/11/30追加)」 >は下記に移動しました。 わざわざご連絡いただきありがとうございます。修正しておきました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[404] ページ移動の通知
投稿者:中野康明
2007/02/20 02:13:25

前橋さんのリンク先にある 「中野康明の雑学ペ-ジ(2003/11/30追加)」 は下記に移動しました。 http://www001.upp.so-net.ne.jp/yasuaki/misc.htm その関連で引かれている「チョン」についての雑文のページも移動しました。 http://www001.upp.so-net.ne.jp/yasuaki/misc/lang/lang35.htm 修正戴ければ幸いです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[402] Re:「C言語 ポインタ 完全制覇」
投稿者:G
2007/02/20 02:13:25

>これは、「Linkable」の定義に対する修正ですから、ひとつめの方です。 >Linkableは、その前のページのFig.5-15におけるLinkableShapeに対応する型で、 >ポインタを3つ持ち、双方向連結リストを構成します。 > >こちらは、双方向連結リストの先頭と末尾を保持することで、「リスト全体」を >表現する構造体です。 > これらが間違っていないのであれば、 私の勉強不足だとわかりました。 じっくりと勉強していきます。 >int a; >int *p; >p = &a; > >とあったとき、pに1加算するだけなら問題ないが、2加算すると規格違反である、 >という意味です。 ># ただし、たいていの処理系では、2だろうと3だろうと、加算するだけなら動きます。 わかりました。 ありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[401] Re:リバーシゲームのはさみ将棋への改造
投稿者:(ぱ)
2007/02/20 02:13:25

>>まず、「クラスのポインタ」が何を指すのか不明です。 >「Board* board = new Board()」の様にnewしたポインタ変数の事です。 クラスとインスタンスは別物なので、その違いは強く意識したほうがよいかと。 new Board()ではBoardクラスのインスタンスが生成(new)され、 「new Board()」という式はそのインスタンスへのポインタを返します。 上の「board」にはそれが代入されるわけですから、boardは、 インスタンスへのポインタであって、「クラスのポインタ」ではありません。 また、「newしたポインタ変数の事です」とのことですが、上の例にある ポインタ型の変数といえば「board」ですが、ここではboardがnewされている わけではありません。 細かいことを言うようですが、 「わかっている人が、厳密さを求められない局面で、適当に省略しながら話す」 のと、 「本当にわかってない」 のでは大違いですので一応念のため。 >僕の憶測ですが、Javaのリバーシゲームでthisを多用していますが、 >これは特に使用しなくていいんですね。 はい。インスタンスフィールドとローカル変数の区別をつけるため、 私はthis.をつけるようにしている、というだけです。 言語がthisを強制していてくれれば、こういう事故も起きないんですけどねえ。 http://d.hatena.ne.jp/higepon/20050329
[この投稿を含むスレッドを表示] [この投稿を削除]
[400] Re:「C言語 ポインタ 完全制覇」
投稿者:(ぱ)
2007/02/20 02:13:25

>こんにちは、はじめまして。 はじめまして。ミスが多く申し訳ありません。 >「 >p.285 >誤 > > typedef struct Linkable_tag { > void *object; > Shape *prev; > Shape *next; > } Linkable; > >正 > > typedef struct Linkable_tag { > void *object; > struct Linkable_tag *prev; > struct Linkable_tag *next; > } Linkable; >」 >とあります。 >しかし、P285にあるプログラムは2つあるのですが、 これは、「Linkable」の定義に対する修正ですから、ひとつめの方です。 Linkableは、その前のページのFig.5-15におけるLinkableShapeに対応する型で、 ポインタを3つ持ち、双方向連結リストを構成します。 >となっていて、2つめは >「 >typedef struct{ > Linkable *head; /* 先頭の要素 */ > Linkable *tail; /* 末尾の要素 */ >}LinkedList; >」 こちらは、双方向連結リストの先頭と末尾を保持することで、「リスト全体」を 表現する構造体です。 >それと、P43のところで、正誤表では、 >「 >と書いてありますので、ふたつ超えた所に向けない限り問題なさそうです。 >」 >となっていますが、本では、 >「 >と書いてありますので、2以上加算しないかぎり問題なさそうですが。 >」 >とあります。 同じ意味のつもりで書いていますが… int a; int *p; p = &a; とあったとき、pに1加算するだけなら問題ないが、2加算すると規格違反である、 という意味です。 # ただし、たいていの処理系では、2だろうと3だろうと、加算するだけなら動きます。
[この投稿を含むスレッドを表示] [この投稿を削除]
[399] Re:リバーシゲームのはさみ将棋への改造
投稿者:SFファン
2007/02/20 02:13:25

>「静的コール」というのが何を指しているのかわかりませんが、 「Board::move(~)」の様な呼び出しの事を指しています。名称は間違ってるかも知れません。 >まず、「クラスのポインタ」が何を指すのか不明です。 「Board* board = new Board()」の様にnewしたポインタ変数の事です。 「オブジェクトに仕事をさせる、ということ」を読ませて貰って、上記の様に一々ポインタ変数をnewせずにパラメータにポインタ変数を持たせて引き継がせればいい事が分かりました。 僕の憶測ですが、Javaのリバーシゲームでthisを多用していますが、これは特に使用しなくていいんですね。 現在、はさみ将棋プログラムに修正をかけていますが、まだまだメモリリークが起きている状態です。 指摘された修正をほぼ全て行なってメモリリークが起きるかどうかテストしたいと思います。 ご回答の程ありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[398] 「C言語 ポインタ 完全制覇」
投稿者:G
2007/02/20 02:13:25

こんにちは、はじめまして。 早速ですが、「C言語 ポインタ 完全制覇」を購入して 読んでいるのですが、正誤表を見てみると、 「 p.285 誤 typedef struct Linkable_tag { void *object; Shape *prev; Shape *next; } Linkable; 正 typedef struct Linkable_tag { void *object; struct Linkable_tag *prev; struct Linkable_tag *next; } Linkable; 」 とあります。 しかし、P285にあるプログラムは2つあるのですが、 1つめは、 「 typedef struct{ void *object; Shape *prev; Shape *next; }Linkable; 」 となっていて、2つめは 「 typedef struct{ Linkable *head; /* 先頭の要素 */ Linkable *tail; /* 末尾の要素 */ }LinkedList; 」 となっていてどこをどのように訂正すればいいかわかりません。 それと、P43のところで、正誤表では、 「 と書いてありますので、ふたつ超えた所に向けない限り問題なさそうです。 」 となっていますが、本では、 「 と書いてありますので、2以上加算しないかぎり問題なさそうですが。 」 とあります。 どちらが正しいのでしょうか? すべてをみたわけではありませんので、ほかはどうなっているのかわかりません。 出版は平成15年7月1日 初版 第7刷発行です。
[この投稿を含むスレッドを表示] [この投稿を削除]