K.Maebashi's BBS

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

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

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

[718] Re:正規表現関連の関数の質問
投稿者:(ぱ)
2007/02/20 02:13:25

>ご教授ありがとうございます。 >GCに少し興味を持ったのですが、お勧めのサイトなどありますか? 私のお勧めサイトというと、ここの参考URLですかねえ。 http://kmaebashi.com/programmer/devlang/array.html あと、紙ものの資料では、大昔の情報処理学会誌に「ごみ集めの基礎と最近の動向」 というのがあって、とてもよかったのですが、現在では入手不能だと思います。 私はというと会社で該当の情報処理学会誌が捨てられる直前に気が付いて、 コピーしておいたのですが、その後数回の引越しで現在行方不明です…だめだめ。 >以下の本を購入しようと思ったのですが、(ぱ)さんは読んだことありますか? > >http://www.amazon.co.jp/exec/obidos/ASIN/0471941484/qid=1136566955/sr=1-1/ref=sr_1_10_1/250-0589622-2949018 すみません、読んでないです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[717] Re:イテレータ(とCPS)
投稿者:(ぱ)
2007/02/20 02:13:25

土曜はとあるイベントにて大阪で飲んだくれておりまして、ずいぶん返事が遅くなりまして すみません。 それプラス、私自身、クロージャに慣れておらず継続もわかっておらず、今回のNykRさんの サンプルはずいぶん荷が重いものでした。とはいえ放り出していては勉強にならんので、 私なりに解釈してみました。間違い等ありましたらご指摘ください。 さて、単に木をイテレートするだけなら、 tree.each(closure(item) { # このitemについてなんかする }); という形のeachメソッドをツリーに装備するのは簡単で、ツリーの中で再帰して、 要素ごとに、渡されたクロージャを呼び出せばよいのですが、こういう形式(内部イテレータ) だと、あるツリーについて、「ここまで走査した」という状態を保存しておけないのが 問題になるわけですよね。その点、NykRさんの提示されたイテレータでは、こういう 書き方も許される。 # ふたつのイテレータでツリーを並列に走査する。 for (ite1 = iterator_GoF(foreachTree_CPS(tr)), ite2 = iterator_GoF(foreachTree_CPS(tr)); !ite1.isDone() && !ite2.isDone(); ite1.next(), ite2.next()) { print(" " + ite1.currentItem()); print(" " + ite2.currentItem()); } これができるのが外部イテレータの強みです。 Cなどで、再帰を使ってツリーを辿る場合、「ここまで走査した」という情報がスタック上に ありますから、スタックが1本しかない以上、ふたつのイテレータを並行して使うことは できないわけです(片方が片方の繰り返しに完全に含まれるなら可能)。 tr = {13,{5,{3,{},{}},{13,{12,{},{}},{}}},{16,{16,{15,{},{}},{}},{17,{},{}}}}; この例では、nodeの[0]にそのノードの値が、[1]に左の子が、[2]に右の子が 入っていますから、再帰で間順で走査するなら以下のようになります。 function internalIterate(node) { if (node.size() == 0) { } else { internalIterate(node[1]); # ...(a) print(" " + node[0]); # とりあえず表示しておく internalIterate(node[2]); } } (a)の箇所で左の子について再帰呼び出しを行い、それが戻ってきてから続きの処理を やっています。「戻ってきてから続きの処理をやる」ことができるのが再帰の嬉しい ところですが、それを期待していては、外部イテレータは作れない。 そこで、「戻ってきてから続きの処理をする」のではなく、「戻ってきてから やってほしい続きの処理をクロージャとして渡す」とすれば、関数から戻ってこなくても よくなる。その変換をしたのがこれ。 function internalIterate(node, cont) { if (node.size() == 0) { cont(); } else { internalIterate(node[1], closure () { # 続きをクロージャで渡す。 print(" " + node[0]); internalIterate(node[2], cont); }); } } # 第2引数には「処理の続きを渡す」のだから、最後に「おしまい」と表示される。 internalIterate(tr, closure() {print("おしまい");}); さて、この状態では、要素ごとに行う処理がprint()に固定されていますから 汎用性がありません。では引数でなにか関数を渡せば、とこうしても、 internalIterate(node[1], closure () { # 続きをクロージャで渡す。 proc(node[0]); # 処理を引数procで渡す internalIterate(node[2], cont); }); これでは内部イテレータと同じですから意味がありません。 そこで、このproc()にも、続きの処理をクロージャで渡してやることにします。 function foreachTree_CPS(proc) { return closure internalIterate(node, cont) { if (node.size() == 0) { cont(); } else { internalIterate(node[1], closure () { proc(node[0], closure() { internalIterate(node[2], cont); }); }); } }; } 外部イテレータの場合、このprocの第2引数をnext()の際に呼び出せばよいわけですね。 なぜならそれが「処理の続き」だから。 イテレータはこうなります。 function iterator_GoF(foreach_CPS, collection) { this = new_object(); this.first = closure () { this.isDone = closure () { return false; }; foreach_CPS(closure (item, cont) { this.currentItem = closure () { return item; }; this.next = closure () { cont(); }; })(collection, closure(){ # ..(b) this.isDone = closure () { return true; }; }); }; this.first(); return this; } イテレータのfirst()が呼び出されたときに、foreach_CPS()を呼び出して、 internalIetrate()を取得し、それに対しcollectionとクロージャを渡しています(b)。 これがつまり元のソースの internalIterate(tr, closure() {print("おしまい");}); に相当するわけですが、「おしまい」と表示する代わりに、isDoneについて、 trueを返すよう関数を差し替えています。 んで、internalIterate()に渡しているproc()では、 this.currentItem = closure () { return item; }; this.next = closure () { cont(); }; currentItemを設定後、nextに対し、contすなわち「処理の続き」をセットしています。 これで、次に利用者がnext()を呼び出したとき、internalIteratorの続きが実行される、と。 NykRさんのソースとは微妙に変わっていますが、こんな解釈でよいでしょうか? # いやあ、実に勉強になりました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[716] プログラミングの入門用言語
投稿者:みずしま
2007/02/20 02:13:25

こんにちは。 大分前の雑記「プログラミングの入門用言語(2003/5/1)」の最後の方で、 > C, Javaライクな文法で、こういう方向性の言語って、現在あるんでしょうか。 てなことを書かれておられましたが、Processing(http://processing.org/)はどう でしょうか?これは、言語はJavaそのものですが、IDEによって、クラス定義などの 初心者にとって面倒そうな部分をうまく隠蔽してあって、単なる手続き型言語のように 使えます。これなら初心者にとっても比較的とっつきやすいんじゃないかと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[715] Re:オブジェクト指向「初」入門
投稿者:kit1
2007/02/20 02:13:25

> 唯一の正解は無いでしょう。場合によって、適切なものを選べば、それ > が正解です。 これが CES さんのやり方の問題なんです。 「is-a の意味は常識的なものとは限らない。場合によって、適切なもの を選べ」というのは、実のところ、まったく意味のない言明です。なぜな ら、CES さんは、is-a という関係が具体的にどうあるべきかを一切述べ ていないからです。 我々は、設計段階で、どういう継承関係にすればうまくいくかを知りたい ため、設計原則を求めているわけです。 たとえば、「常識的に考えた is-a 関係に対して、継承を当てはめれば良 い」というのは、正方形と長方形の例のようにうまくいかない例外もあり ますが、かなり使える原則です。 また、「LSPに従うオブジェクト同士に対して、継承を当てはめれば良い」 というのは、常に利用可能な原則です。 ところが、CES さんは、「継承してうまく動くような関係が is-a である。 したがって、継承してうまく動くような関係に対して、継承を当てはめれ ば良い」と言ってるに過ぎないわけです。これは見て分かるようにトート ロジーに過ぎず、設計の指針としては、全く役に立たないわけです。 結局、CES さんの主張は、LSP どころか、(常にうまくとは限らない)常識的 な is-a 関係による継承関係の設計よりも、さらに劣るものにしか見えません。 また、CES さんは下記のように書いていますが、これはそもそも意味不明です。 > 全く同じ属性と振る舞いを持つクラスは、同じクラスだと考えるべきです。 > これは、「LSP が成り立つならば is-a も成り立つ」と言い換えることもできます。 この二つの文章のうち、一つ目の文章は、クラスとクラスの等価関係に 関する文章です。 二つ目の文章は、クラスとクラスの包含関係に関する文章です。 等価関係に関する文章と、包含関係に関する文章が、同一の意味である という発想は、まったくもって非論理的だと私は思います。 なぜ、この二つの文章が等価だと発想されたのか、残念ながら、私には 理解できません。 一つ目の文章は正しいと思います。 しかし、一つ目の文章から二つ目の文章を導くことはできません。 なお、Martin 氏の文章を読み返してみて、私がこれまで説明で使って 用語法が、Martin 氏の用語法と異なっているのに気づきました。 私がこれまで 1. オブジェクトの振舞いに関する is-a 2. オブジェクト自身に関する is-a という二つの言葉で区別してきたことを、Martin 氏は 1. 振舞いの is-a == オブジェクト(CamelCase にした名詞)の is-a 2. 物(子文字で始まる名詞)の is-a と呼んでいますね。 まあ、独立に読んでいれば意味は通じると思いますが、併せて読むと 混乱するのであまり良くありませんね。どうも申し訳ない。 > オブジェクト指向の第一目的は「わかりやすくすること」であると(今 > は)思っています > 本来、無関係のオブジェクト同士を継承関係にするのがわかりやすいで > すか? 私が欲しいのは良い設計指針であって、オブジェクト指向の第一目的は 何かという問いの答は実はどうでもいいんですが(なぜなら、人によって 答がそれぞれ違うので、そんなことの統一見解を決めても実益がないから です)、それは置いておいて、かなり誤解されていると思います。 設計手順としては、まず常識的な is-a を使って継承関係を考えてみた 上で、それを LSP で検証すればいいんですよ。検証に通らない場合には、 たとえ常識的なis-a 関係であっても、継承関係にはしません。検証に通 れば、もちろん継承関係にします。 簡単でしょう? 本来無関係のオブジェクト同士うんぬんなどと悩む必要はありません。 なお、もし本来無関係だと思っていたオブジェクト同士にLSPが成り立つ のであれば、実はそのオブジェクト同士は、たぶん無関係じゃないんですよ。 しかし、通常のソフトウェア開発で、そういう発見を必要とすることは あまりありませんから、無関係だと思うオブジェクト同士について、 いちいちLSPを検証してみる必要はありません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[714] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

>> 正方形は長方形のサブクラスであるとしても成り立つ場合は既に >> 書きました。is-a と LSP をどうしても両立させられない例を一 >> つでも出していただけませんか。 > >CES さんご自身が、正方形を長方形のサブクラスに『しない』方が >いい場合があると、[709]で認めているじゃないですか。常識的に >は、正方形 is-a 長方形ですから、当然、正方形は長方形のサブク >ラスとして継承関係を結ぶべきですし、Robert C. Martin 氏のエッ >セイでも、その方法をまず勧めています。しかし、そうしない方が >いい場合もあるわけですから、オブジェクト自身の is-a は必ずし >も判断基準に使えません。 俺はそういうことを言っているのではありません。 LSP なんか関係なく、「正方形 is a 長方形にならない場合もある」ということです。 その場合は、正方形が長方形でないのは何ら問題ではないのですから、「is a と LSP が矛盾する」とは言えません。 「常識的には」と書かれていますが、それが間違いの元です。 世の中に客観的な視点など存在しないというのは以前に書きました。 正方形 is a 長方形というのは、客観的に見えますが、「数学的に都合がいい見方」に過ぎません。常識と言うのも、大多数に都合がいい見方に過ぎません。真理ではないのです。 件の文献の勘違いは「長方形」の定義が曖昧なことです。 「正方形 is a 長方形」は数学に都合がいい見方、「縦と横の長さが独立していなければならない」は、このプログラムに都合がいい見方であって、数学に都合がいい見方ではない。 どちらの見方が間違いというのではありません。どちらも場合によっては正解なのですが、その「場合」が統一されていないのが間違いなのです。 このプログラムが「長方形」に何を期待しているのかが明確になっていないのがいけないのです。 大本の問題は、何のためのプログラムなのかを明確にしないまま、コードだけ示して煙に巻こうとしたことですね。 仮に、「常識的に考えて、正方形 is a 長方形なのだから、当然サブクラスにすべきだ」というのが正しいとして、では「りんご」は何のサブクラスにすべきですか? 常識的に考えて「果物」のサブクラス? それとも「バラ科の植物」? スーパーマーケットのシステム開発だったら「商品」のサブクラスにすべきではないですか? 唯一の正解は無いでしょう。場合によって、適切なものを選べば、それが正解です。 「正方形 is not a 長方形」にすべき場合は確かにあるでしょう。 それは、LSP に都合が悪いからそうなったのではなく、作りたいソフトの目的に合致しないからそうなったのです。 「is-a は LSP と両立できなかったので泣く泣く諦めた」のではなく「そもそも両立する必要が無かった」のです。 現在は is-a が推奨されています。百歩譲って has-a もまぁ認めるとしましょう。 問題は、「LSP さえ成り立つのなら、まったく無関係のクラス同士を継承関係にしていいのか」ということです。 (どういう設計になるのか知りませんが)LSP が成り立つのなら、車を鳥のサブクラスにするのもアリなのですか? オブジェクト指向の第一目的は「わかりやすくすること」であると(今は)思っています(以前、この掲示板に長期滞在したときは「バグを減らすこと」だと思っていました。考えは変わる可能性があります)。 本来、無関係のオブジェクト同士を継承関係にするのがわかりやすいですか? >> よろしければ、おすすめの本を紹介していただけないでしょうか。 > >今回紹介したエッセイ自身を含んだ、Robert C. Martin 氏の >「アジャイルソフトウェア開発の奥義」はいかがでしょう? >http://hamasyou.com/archives/System/aeeoeeueaconoeoeass.php >http://hamasyou.com/archives/System/aeeoeeueaoeeoeaass.php >に長めの紹介があります。 持ってますけど読んでませんでした。 OCP や LSP の評判を聞いて買ったのですが、買ったきりで。 そのうち読むことにしましょう。 こちらにも一点、考え直したことがあったので、最後にそれについて言及します。 オブジェクト指向において、オブジェクトを特徴付けるものは、属性と振る舞いです(プロパティとメソッドとか、メンバ変数とメンバ関数とか、言語によって呼び方はいろいろあるでしょうが)。 つまり、全く同じ属性と振る舞いを持つクラスは、同じクラスだと考えるべきです。 これは、「LSP が成り立つならば is-a も成り立つ」と言い換えることもできます。 しかし、逆に言えば「違うクラスに、全く同じ属性と振る舞いを持たせるべきではない」「関係の無いクラスに、LSP を成り立たせるべきではない」とも言えます。 そう考えれば、「is-a が成り立つのならば LSP が成り立つのは当然」「is-a が成り立たないのならば、LSP も成り立たせるべきではない」のではないでしょうか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[713] Re:オブジェクト指向「初」入門
投稿者:kit
2007/02/20 02:13:25

> 俺がプログラミングを初めてまだ7年、オブジェクト指向が分かっ > てきたのはここ1、2年ほどのことですのでね。 意外と長いんですね。 私はプログラミング歴は24年ぐらい、オブジェクト指向に関しては プログラミング言語C++第1版の和訳や、Smalltalk-80のオレンジブッ クの和訳が出た頃からですから、20年弱くらいですかね。 その前に、先輩から米国byte誌のSmalltalk-80特集号を見せてもらっ たこともありましたが。 > 正方形は長方形のサブクラスであるとしても成り立つ場合は既に > 書きました。is-a と LSP をどうしても両立させられない例を一 > つでも出していただけませんか。 CES さんご自身が、正方形を長方形のサブクラスに『しない』方が いい場合があると、[709]で認めているじゃないですか。常識的に は、正方形 is-a 長方形ですから、当然、正方形は長方形のサブク ラスとして継承関係を結ぶべきですし、Robert C. Martin 氏のエッ セイでも、その方法をまず勧めています。しかし、そうしない方が いい場合もあるわけですから、オブジェクト自身の is-a は必ずし も判断基準に使えません。Robert C. Martin 氏が、エッセイの 「本当の問題」「何が悪いのか?」「Design By Contract」のとこ ろで説明しているのは、そういうことです。オブジェクト自身の is-a で考えるのは誤りであり、オブジェクトの振舞いに関する is-a で考えないといけないのです。前に出た円と楕円の話も同じ です。 このあたりは、和訳を読むよりも、原文 http://www.objectmentor.com/resources/articles/lsp.pdf の "What Went Wrong" のところを読んだ方が、むしろ理解しやす いかもしれません、「a Square object is definitely not a Rectangle object.」と書いてありますから。和訳の「決定的な違 いがあるのです。」という表現では、残念ながら、ここの is-a と is-not-a のニュアンスが消えてしまっています。私は原文の方を 先に読んだので、ここのところが非常に強く印象に残りました。 なぜ、オブジェクト自身の is-a 関係が継承関係の設計に使えない 場合があるのか、そのことを説明しているのが LSP です (ただし、 正方形や円のケースでは、LSP 以外にも、メモリ効率という別の理 由もあります)。継承関係の設計において、オブジェクト自身の is-a 関係は使えない場合がある弱い判断基準なわけですが、LSP は常に使える絶対的な判断基準なわけです。実はLSP(オブジェクト の振舞いに関する is-a) の方が、オブジェクト自身のis-aよりも むしろ本質的な原則なわけです。 現在では、has-a の関係は、継承よりも委譲を使うのが良い解だと されていますが、昔は has-a でも継承を使うことが良くありまし た。今でもたまにそういうプログラムを見ることがあると思います。 これも、アプリケーションを限定すれば、has-a で LSP を満たす 場合があることから来ているわけです。has-a で継承して問題のな いアプリケーションは、オブジェクト自身の is-a 関係で継承して 問題のないアプリケーションよりも、はるかに少ないので廃れてき ているわけですが。 has-a が廃れてきているのに is-a がそうではないのは、オブジェ クト自身についてis-a の関係が成り立つ場合のほとんど(ただし全 てではない)で、同時に、オブジェクトの振舞いに関する is-a 関 係(すなわちLSP)も満たすからです。 > よろしければ、おすすめの本を紹介していただけないでしょうか。 今回紹介したエッセイ自身を含んだ、Robert C. Martin 氏の 「アジャイルソフトウェア開発の奥義」はいかがでしょう? http://hamasyou.com/archives/System/aeeoeeueaconoeoeass.php http://hamasyou.com/archives/System/aeeoeeueaoeeoeaass.php に長めの紹介があります。 ただ、和訳だと上述したように、ニュアンスが失われる部分はある でしょうね。また、data中心でモデリングした結果の扱いについて は、この本の主張に異論がある場合もあるでしょう。この本では常 にOOAを優先すべしという方向ですが、data中心でモデリングした 結果の方を優先した方がいい場合もある筈です。 私は、Robert C. Martin 氏自身の名前は、亡くなられた石井勝さ んのページで知りました。 http://www.objectclub.jp/community/memorial/homepage3.nifty.com/masarl/article/oo-principles.html 石井さんがこのページを書かれたのは1999年ですね。 今ではLSPは有名な原則ですが、これが広まったのは Liskov 氏自 身の功績というよりは、Robert C. Martin 氏の功績の方が大きい と思います。私がこの法則を知ったのも今回のエッセイを読んだ からですし、google で The Liskov Substitution Principle を 検索して最初に出てくるのも、このエッセイですし。
[この投稿を含むスレッドを表示] [この投稿を削除]
[712] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

>もちろん、「オブジェクトが is-a であるか」と「オブジェクトの『振舞い』 >が is-a であるか」の二つが矛盾しない場合は問題ありません。しかし、矛盾 >した場合に優先すべきなのは、LSP の方です。 >しかしどうやら CES さんは、矛盾した場合、LSP よりも前者を優先すべきだ >とお考えのようですね。 どちらかと言えばそうかもしれません。 LSP を守ることも重要ですが、まずはオブジェクトの is-a を優先し、その上で LSP が守られるように都合をつけるべきだと思います(結果的には、両方守るべきです)。 >Robert C. Martin がこの文書を発表してから、もう10年近く、Liskov から >数えれば、もう15年以上経っており、私は既に常識的な知識だと思っていまし >たが、驚かれたということは、どうやらそうではなかったようですね。 俺がプログラミングを初めてまだ7年、オブジェクト指向が分かってきたのはここ1、2年ほどのことですのでね。 >そもそも LSP や、この文書が有名になったのは、「オブジェクトが is-a である >か」という判定条件が成り立たない場合があるということを、はっきりと示 >しているからだと思うのですが。 >is-a だけで済むのであれば、わざわざ原則として掲げる必要も、文書で解説 >する必要もありません。 >失礼ながら、御自身の考えを他人の掲示版で開陳されるよりも先に、もう少し >オブジェクト指向関係の良書で勉強された方が良いのではないでしょうか。 よろしければ、おすすめの本を紹介していただけないでしょうか。 >少なくともこれまでのところ、私は CES さんの意見に説得される可能性は >ありません。CES さんの考えを証明する具体的な例を一切目にしていません >ので。前の投稿でも書きましたが、私は机上の空論は嫌いですし、具体的な >例のない議論に説得されることは決してありません。 >(ぱ)さんも同様ではないかと思います。 その言葉はそっくりお返しします。 正方形は長方形のサブクラスであるとしても成り立つ場合は既に書きました。 is-a と LSP をどうしても両立させられない例を一つでも出していただけませんか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[711] Re:オブジェクト指向「初」入門
投稿者:kit
2007/02/20 02:13:25

> いや恐れ入った。 > 「オブジェクトが is-a であるか」は守られなくてもいいのか。 その通りです。 もちろん、「オブジェクトが is-a であるか」と「オブジェクトの『振舞い』 が is-a であるか」の二つが矛盾しない場合は問題ありません。しかし、矛盾 した場合に優先すべきなのは、LSP の方です。 しかしどうやら CES さんは、矛盾した場合、LSP よりも前者を優先すべきだ とお考えのようですね。 Robert C. Martin がこの文書を発表してから、もう10年近く、Liskov から 数えれば、もう15年以上経っており、私は既に常識的な知識だと思っていまし たが、驚かれたということは、どうやらそうではなかったようですね。そも そも LSP や、この文書が有名になったのは、「オブジェクトが is-a である か」という判定条件が成り立たない場合があるということを、はっきりと示 しているからだと思うのですが。 is-a だけで済むのであれば、わざわざ原則として掲げる必要も、文書で解説 する必要もありません。 失礼ながら、御自身の考えを他人の掲示版で開陳されるよりも先に、もう少し オブジェクト指向関係の良書で勉強された方が良いのではないでしょうか。 あるいは、もし、「オブジェクトが is-a であるか」は LSP よりも優先する という考えをどうしても主張されたいのであれば、掲示版はそもそも不向きな メディアだと思います。 なぜ LSP よりも優先するのかを、適切な例を含めた上で、ご自分の Web ペー ジで解説された方が良いと思いますよ。 もし、Barbara Liskov や Robert C. Martin も優れた考えであるのなら、 独立した文書として公開する価値が十分あると思います。 少なくともこれまでのところ、私は CES さんの意見に説得される可能性は ありません。CES さんの考えを証明する具体的な例を一切目にしていません ので。前の投稿でも書きましたが、私は机上の空論は嫌いですし、具体的な 例のない議論に説得されることは決してありません。 (ぱ)さんも同様ではないかと思います。 > 「正方形は長方形のサブクラスであるか?」という質問に、唯一の正解はあり > ません。答えは、数学に厳密である必要がある場合には YES 、そうでない場 > 合には NO になります。 あるアプリケーションが、Robert C. Martin が例に示しているような 条件と、数学的に厳密であるという必要があるという条件のどちらも 同時に満たしている必要がある場合はどうすれば良いのでしょうか? もちろん、答えは NO です。 従って、上に書いた CES さんの答え「数学に厳密である必要がある 場合には YES」は、条件に抜けがある誤った答であるということに なります。 私には、CES さんが LSP の本質を理解していないように見えますね。 理解しているなら、上のような文章が出てくる筈はありません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[710] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

#ちょっと落ち着いて整理しましょう… >だったら最初からそう書けばいいのに。 >つか、それを読み取れというのは無茶と言うものです。 これは、(お互いに)「自分ではそう言ったつもりだったけど、相手には伝わらなかった」ということで傷み分けにしましょうや。 >私が最初から言っているのは、 > >「クラスを辞書で引いて分類と書いてあるからといって、プログラムの設計の際に、 >クラスを分類として捉えることが正しいことになるわけではない」 > >ということです。 なるほど。 俺は「辞書的用語」と「術語」の問題(あくまで用語の問題で、実際の設計はまた別問題)だと思っていました。 前橋さんは「どう呼ぶか」よりも「実際にどう設計するか」を問題視されていた。そこが齟齬の原因。 ちなみに、それに関する俺の答えは [706] > もちろん、実装の都合上、必ずしもそうとは言えないクラスが出てくることはあり得るでしょう。しかし、それらは例外として考えるべきであり、基礎としては無駄ではありません です。一言で言えば「(例外はあるかもしれないが)原則的に、辞書的意味と同じと考えていい」ということ。 後半は感情的になって煽ってしまったことはお詫びいたします。 #最後の最後で何とかまとまってよかった。
[この投稿を含むスレッドを表示] [この投稿を削除]
[709] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

> リンク先の文章で示されている「正方形を長方形のサブクラスにするのが誤り」という話が的外れであることは、ずいぶん前に書いてますよ。 と言うだけでは何なのでちょっと補足。 「正方形は長方形のサブクラスである」というのは、数学的に見れば、確かにそうです。 しかし、長方形の数学的な性質とは、「4つの角が全て直角である四角形」というだけであって「縦と横の長さが独立していなければならない」という要件はありません。 リンク先の文章では、その数学的には必要とされていない要件を要求しているのですから、もはや「数学的には正方形は長方形のサブクラスだ」という前提は成り立たないのです。 では、正方形クラスを長方形クラスのサブクラスとして設計するのは誤りなのでしょうか? そうとは限りません。 数学的に正しいプログラムを書く必要があって、長方形の縦と横の長さが独立していなければならないという要件が無いのなら、この設計は全く妥当なものです。 「正方形は長方形のサブクラスであるか?」という質問に、唯一の正解はありません。 答えは、数学に厳密である必要がある場合には YES 、そうでない場合には NO になります。 提示された文章では、それがちぐはぐだからおかしなことになっているのです。 [653] あたりで言っているのはそういうことです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[708] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

>> 「サブクラスの方が機能が上」という考え方だと、is-a の関係を考えた時 >> に「機能が豊富なものは機能がショボいものの一種」ということになって変 >> だよね。 > >変じゃないですよ? >Robert C. Martin が、Liskovの置換原則に関する有名な文書 >http://www2.ocn.ne.jp/~yamagu/object/LSP-J.pdf >で述べた通り、継承の際に使う is-a の関係は、「オブジェクトが is-a で >あるか」ではなく、「オブジェクトの『振舞い』が is-a であるか」で判断 >すべきです。 >「機能が豊富なものは機能がショボいものの一種」というのは、この原則を >平易な言葉で言い替えたものに過ぎません。 >オブジェクト指向設計の大原則です。 いや恐れ入った。 「オブジェクトが is-a であるか」は守られなくてもいいのか。 LSP を守るべきであるのは当然だけど、リンク先の文章で示されている「正方形を長方形のサブクラスにするのが誤り」という話が的外れであることは、ずいぶん前に書いてますよ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[707] Re:オブジェクト指向「初」入門
投稿者:kit
2007/02/20 02:13:25

抽象論は苦手なので、このスレッドには書かないようにしようと思ってたの ですが、堂々めぐりしているように見えるので。 > 「サブクラスの方が機能が上」という考え方だと、is-a の関係を考えた時 > に「機能が豊富なものは機能がショボいものの一種」ということになって変 > だよね。 変じゃないですよ? Robert C. Martin が、Liskovの置換原則に関する有名な文書 http://www2.ocn.ne.jp/~yamagu/object/LSP-J.pdf で述べた通り、継承の際に使う is-a の関係は、「オブジェクトが is-a で あるか」ではなく、「オブジェクトの『振舞い』が is-a であるか」で判断 すべきです。 「機能が豊富なものは機能がショボいものの一種」というのは、この原則を 平易な言葉で言い替えたものに過ぎません。 オブジェクト指向設計の大原則です。 > 集合論(というか論理学のベン図)で考えれば、スーパークラスはサブクラ > スよりも一段階抽象的なので、直接比較できないことはわかるよね。 これは、「オブジェクトが is-a であるか」を継承関係の設計の判断基準に 使うべきだと述べているように見えます。これは、第一近似として使いやすい 方法ではありますが、Robert C. Martin の文書で示されている通り、厳密に 考えると誤りであり、Liskovの置換原則の方を優先すべきです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[706] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

>>「術語としてのクラス」に「辞書的な『分類』という意味」を期待する > >ことについてとやかく言った覚えはありません。 >いや、とやかく言っている、というのならその部分を引用して示してください。 このへん@684 > でも、「クラス」という言葉の辞書的定義が「分類」だったからといって、 > 術語として使われるときそのままの意味とは限らないし、「クラス」という > 言葉を選んだ人が間違えたのかもしれない。だから、その言葉の意味に > 過剰な期待をしてもしょうがないのでは、と言っているのです。 >私が最初から言っているのは、 > >「クラスを辞書で引いて分類と書いてあるからといって、プログラムの設計の際に、 >クラスを分類として捉えることが正しいことになるわけではない」 > >ということです。 だったら最初からそう書けばいいのに。 つか、684 からそれを読み取れというのは無茶と言うものです。 >[684]での引用を再度引用しますが、 > >>この議論の最初のほうで、CESさんは >>>例えば、「クラス」という用語の意味は「分類」であって、「原型」ではありませんから、 > >と書いています。「ありません『から』」なんだというのでしょうか。 >もちろん、術語は用途をちゃんと表しているのにこしたことはないけれど、 >術語の方から、設計や分析についてのあるべき姿を導くことはできない。 「クラス」という用語の意味は「分類」であって、「原型」ではありませんから、「クラスはオブジェクトを作る原型になるもの」ではなく「クラスはオブジェクトを分類したもの」だと捉えるべきだ、ということです。 そして、そう捉えることは、まったく自然なように思われるのです(もちろん、実装の都合上、必ずしもそうとは言えないクラスが出てくることはあり得るでしょう。しかし、それらは例外として考えるべきであり、基礎としては無駄ではありません)。 >だから私は、術語なんかに期待するのではなく、 > >>クラスを分類として考えるのがよいとCESさんがお考えなら、それが具体的に >>有効であるケースを、例示して主張するのがよいのではないでしょうか。 > >と、具体的な例示をするのがよいのでは、と言っているのです。 「クラス」という言葉の「辞書的用法」と「述語的用法」に関しての議論だとばかり思っていたので、「クラスを分類だと考えていない」とはまさか思いませんでした。 こうも書かれているのに。 ># クラスを分類とする考え方を否定しているわけではありません。 > 「そのへんの入門書にある考え方だと、こういう例ではこういうモデリングを > してしまいがちだけど、分類として考えればこんなモデリングになって、 > こういう拡張をするときのことを考えたらこっちのほうが修正箇所が > はるかに少なくてすむよね」とか。 「サブクラスの方が機能が上」という考え方だと、is-a の関係を考えた時に「機能が豊富なものは機能がショボいものの一種」ということになって変だよね。 集合論(というか論理学のベン図)で考えれば、スーパークラスはサブクラスよりも一段階抽象的なので、直接比較できないことはわかるよね。 「サイヤ人とスーパーサイヤ人はどっちがすごいか」は、暗黙のうちに「サイヤ人=スーパーじゃないサイヤ人」という仮定を置かず、「サイヤ人はスーパーサイヤ人のスーパークラス」とする限り、比べられない(作中ではこの仮定が暗黙のうちに成立している)。 「スーパーじゃないサイヤ人とスーパーサイヤ人」ではスーパーサイヤ人の方がすごいけど、スーパーじゃないサイヤ人はスーパーサイヤ人のサブクラスではない。 …でいい? 「こう考えるといいよね」というよりも「こう考えないと明らかに変だよね」という感じなので、修正工数云々で対比することはできない。
[この投稿を含むスレッドを表示] [この投稿を削除]
[705] Re:多態性(ポリモーフィズム)について
投稿者:CES
2007/02/20 02:13:25

ふと思ったのは、「オブジェクト指向データベース」っていう言葉からして破綻している気がするなぁ…というものでした。 「オブジェクト指向データベース」って何なんだ…と思って、易しい入門を読んでみましたが、そこでは結局、「データを隠蔽し、getter と setter を持っているものがオブジェクトである」という程度でした。 結局のところ、「データベース」である以上は「オブジェクト指向言語と相性のいい永続化ストア」を脱し切れなくて、一歩踏み出すならば「オブジェクトベース」にならなければいけないような気がします(その具体的な形がどうなるかまでは分かりませんが)。 #まぁ、汎用機時代からデータスキーマを使いまわすような運用では、そうそうパラダイムシフトも起こせないでしょうけど。
[この投稿を含むスレッドを表示] [この投稿を削除]
[704] Re:オブジェクト指向「初」入門
投稿者:(ぱ)
2007/02/20 02:13:25

>まだ酔っ払ってますか? 何故そんな言葉を持ち出されたのかさっぱり分かりません。 スーパークラスやサブクラスは術語であり、悟空やベジータはスーパーサイヤ人です。 単純に置き換えただけですが何か? >「術語としてのクラス」に「辞書的な『分類』という意味」を期待するのは、 >まったく過剰ではないと思える、ということです。 だったら最初からそう書けばいいのに。 つか、 >>「クラス」も「スーパークラス」も、全く過剰だとは思えないので。 これからそれを読みとれというのは無茶というものです。 で、私は、 >「術語としてのクラス」に「辞書的な『分類』という意味」を期待する ことについてとやかく言った覚えはありません。 いや、とやかく言っている、というのならその部分を引用して示してください。 私が最初から言っているのは、 「クラスを辞書で引いて分類と書いてあるからといって、プログラムの設計の際に、 クラスを分類として捉えることが正しいことになるわけではない」 ということです。 [684]での引用を再度引用しますが、 >この議論の最初のほうで、CESさんは >>例えば、「クラス」という用語の意味は「分類」であって、「原型」ではありませんから、 と書いています。「ありません『から』」なんだというのでしょうか。 もちろん、術語は用途をちゃんと表しているのにこしたことはないけれど、 術語の方から、設計や分析についてのあるべき姿を導くことはできない。 だから私は、術語なんかに期待するのではなく、 >クラスを分類として考えるのがよいとCESさんがお考えなら、それが具体的に >有効であるケースを、例示して主張するのがよいのではないでしょうか。 と、具体的な例示をするのがよいのでは、と言っているのです。 私がどのような例示を求めているのかについて、誤解があるといけないので テンプレまで書いてあげました。 >「そのへんの入門書にある考え方だと、こういう例ではこういうモデリングを >してしまいがちだけど、分類として考えればこんなモデリングになって、 >こういう拡張をするときのことを考えたらこっちのほうが修正箇所が >はるかに少なくてすむよね」とか。 ここまでやっているのにさ。 回答はこれだぜ。 >例示が必要でしょうか? 「is-a」「汎化-特化」の考えは、まさに分類だと >思うのですが(「汎化」「特化」という用語を誰が考えたかは知りませんが、 >いくらこれが術語だからと言って「低機能」「高機能」という意味でないのは >明らかでしょう)。 (特に自分とこの掲示板で)こんな終わり方をするのは私も嫌なんですが、 意思の疎通をする気がないようなので、これまでとしたいと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[703] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

>>何が過剰なのかわからないのです。 > >[684]に書いたことを繰り返すつもりはありません。 #こういう終わり方は大嫌いなのですが 「意思の疎通ができてないみたいなので、これまでとしましょう」って打ち切っていいですか? >>「クラス」も「スーパークラス」も、全く過剰だとは思えないので。 > >もはや日本語むちゃくちゃになっていませんか? > >「スーパーサイヤ人に過剰な期待をするのはいかがなものか」 >「悟空もベジータも、全く過剰とは思えない」 > >意味不明です。 まだ酔っ払ってますか? 何故そんな言葉を持ち出されたのかさっぱり分かりません。 最初の文の意味が通じなかったのならば補足します。 「術語としてのクラス」に「辞書的な『分類』という意味」を期待するのは、まったく過剰ではないと思える、ということです。 何が「過剰な期待」で、何が「過剰でない期待」なのか。術語には何なら期待していいのか。 [684] を何度読み返しても、それがわからないんですよ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[702] crowbar ver.0.4のバグを修正しました
投稿者:(ぱ)
2007/02/20 02:13:25

># つhttp://www.shiro.dreamhost.com/scheme/docs/cont-j.html 紹介していただいたshiroさんのページは、以前読んだことはあったのですが、 あまり理解できずにそのままになっていました。 そこで今回、以下のページのActionScript版をベースに、crowbar版を書いて 試してみたところ… クラッシュしました。 http://torus.jp/memo/x200403/nandemo_keizoku_as.rd.html 調べてみたら、「配列リテラルの要素にオブジェクトを格納すると、一時的に スタックからの参照が切れることがあり、そのタイミングでGCすると死ぬ」という 潜在バグが(おそらくver.0.2から)あり、かつ、ver.0.4では「毎回GCする」という テスト用の状態でリリースしてしまったために発覚しました。 取り急ぎ修正版をリリースしました。毎度テストが甘くすみません。 力尽きたので今日はここまでです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[701] Re:正規表現関連の関数の質問
投稿者:タイガー
2007/02/20 02:13:25

>crowbarでも、CRB_dev.hにあるオブジェクト確保系の関数群において、自動的に >参照をスタックに積んでしまうことは可能です。ネイティブ関数実行後スタックを >戻す処理も、処理系側で苦もなくできます。 >なぜ今そうなっていないかというと… うーん、何故なんでしょう? (^^; >たとえば、オブジェクトを確保して、すぐに既存の配列の要素にセットする、 >という場合、特にスタックに積む必要はないのでその辺の無駄を嫌ったような >気がしますが、現状の仕様は、「いつGCが起きる可能性があるか」という点について >crowbarの内部実装をネイティブ関数の作者に晒していることになりますから、 >大変よろしくないですね。次バージョンでは修正します。 > >ネイティブ関数側で、大量のオブジェクトの確保/破棄を繰り返すような処理が >あるとすると、スタックが大量に無駄になりますが、そんなことわざわざ >ネイティブ関数で書かないですよねえ… あるいはその場合でも、 >ネイティブ関数用を呼び出したときのCRB_LocalEnvironmentに >local referenceの表を持ち、スタックではなくそちらに参照を入れるようにして >おけば、ネイティブ関数のプログラマに手で解放させることも不可能ではないですし。 ご教授ありがとうございます。 GCに少し興味を持ったのですが、お勧めのサイトなどありますか? 以下の本を購入しようと思ったのですが、(ぱ)さんは読んだことありますか? http://www.amazon.co.jp/exec/obidos/ASIN/0471941484/qid=1136566955/sr=1-1/ref=sr_1_10_1/250-0589622-2949018
[この投稿を含むスレッドを表示] [この投稿を削除]
[700] Re:多態性(ポリモーフィズム)について
投稿者:happie
2007/02/20 02:13:25

>そちらのblogも拝見しました。 ありがとうございます。 >「業務アプリケーションにはオブジェクト指向は >向かない」というのは同意見です。まあ業務アプリでも、フレームワークや、 >アプリケーションの「機能」の側でOOを使うところはたくさんありますが、 >「データ」に処理は結びつかないと思います。 そうなんですね。処理系、GUIアプリだとOOは相性はいいのですが、多くの本で、その辺の区別をせずに何でもOOがいいとして、で業務アプリを例にとって解説しているのですが、構造を見るとあまりOOっぽくない。最近流行のDIも、シングルトンを使ってかつインターフェースに対する実装クラスは一つが基本なので、これってOOなのって思ってしまいます。 >ということで、総論では賛成ですが、「メモリ中心では無理だから」という方の >理由付けはいらないんじゃないでしょうか。メモリに載ろうが載るまいが、 >あるいはオブジェクト指向データベースがディスク上のデータを透過的に見せて >そのへんの問題をすべてクリアしてくれようが、データに処理が結びついていない以上、 >やっぱりオブジェクト指向には合わないのだと思います。 確かにそのとおりですね。データと処理が結びつかないという議論とは別でした。 形上、オブジェクト指向的に作ったところでデータベースとの絡みでいろいろと問題が出てくるし、データベース中心に考えていった方がいいんじゃない、ということで、業務アプリケーションはオブジェクト指向に向いていないということを言おうとしていました。現在のORマッピングツールでは駄目ですね。おっしゃるとおり、たとえオブジェクト指向データベースで完全に透過的になったとしても、やっぱり「オブジェクト指向的」としか言えないでしょうね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[699] Re:多態性(ポリモーフィズム)について
投稿者:(ぱ)
2007/02/20 02:13:25

>はじめまして。happieと申します。 はじめまして。 >また『ポインタの完全制覇』や「疑り深いあなたのためのオブジェクト指向再入門」 >については、本質的なところを突いているため大変興味深く読ませていただきました。 ありがとうございます。 >(ぱ)さんは、ポリモーフィズムに関してあまり記述がなかったように思いますが、 >どのようにお考えですか。 ポリモルフィズムは重要な概念だと思います。 「疑り深い~」でポリモルフィズムについて触れていないのは、今のところまで書いて 力尽きたというか、優先度がそれほど高くないと思ったからです。 マルチプルインスタンスについては、オブジェクト指向を普通に使っている人なら 誰でも普通に使っているにもかかわらず、そして初心者は結構そこでつまずくにも 関わらず、ほとんど誰もそれを重要であると声に出して言わないので、 これはまずいだろ、と思いあれを書いたわけですが、インタフェースと ポリモルフィズムに関しては、私は重要だと思いますし、誰もが重要だと言いますから、 特に声を上げる必要もないかなあ、と。 ただ、ポリモルフィズムが実際にどういう場面でどこまで使えるか、という点に ついては注意を払う必要があるとは思います。 最近、この掲示板の[649]にも書いていますが、「CADを作るとき図形にdraw() メソッドを付けるのは正しいのか」という話を、私はしょっちゅう出しています。 そちらのblogも拝見しました。「業務アプリケーションにはオブジェクト指向は 向かない」というのは同意見です。まあ業務アプリでも、フレームワークや、 アプリケーションの「機能」の側でOOを使うところはたくさんありますが、 「データ」に処理は結びつかないと思います。 業務アプリでは、たくさんのテーブルがあり、また、さらにたくさんの「機能」が あります。そして、しょっちゅう機能追加を行っても、そうそうテーブル定義には 変更を加えません。データが何よりえらいのであって、処理がデータに依存しても、 データが処理に依存してはいけない。これは基本的には「CADで図形にdraw()メソッドを 付けるべきではない」というのと同じことだと思います。 ということで、総論では賛成ですが、「メモリ中心では無理だから」という方の 理由付けはいらないんじゃないでしょうか。メモリに載ろうが載るまいが、 あるいはオブジェクト指向データベースがディスク上のデータを透過的に見せて そのへんの問題をすべてクリアしてくれようが、データに処理が結びついていない以上、 やっぱりオブジェクト指向には合わないのだと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[698] Re:正規表現関連の関数の質問
投稿者:(ぱ)
2007/02/20 02:13:25

>>これは、Cの関数を抜けた後の話ですよね。レジストリに登録するという。 >>crowbarでは、Cの関数の実行中でも、ヒープ関連の関数を呼び出すと >>GCが動く可能性がありますから、ひとまずスタックに積まなければなりません。 > >私はよく分かっていないのですが、このcrowbarのアプローチは >メジャーなのですか? たぶん、メジャーでも、望ましいものでもないと思います。 Rubyだと、GCがCスタックをスキャンするから何もしなくてよく、 Pythonだと、参照カウンタを上げたり下げたりを手でやらなければいけなかったと 思いますが(過去形?)、たとえばJavaのJNIでは、別にCスタックをスキャンする わけでもないのに、確保したオブジェクトについては特に何もする必要はありません。 JavaHouseにある首藤さんの記事によれば、 http://java-house.jp/ml/archive/j-h-b/013314.html | JNI: native method のフレームごとに local references (の表) を用意、 | local references から辿れるオブジェクトは回収しない。 とのことです。 crowbarでも、CRB_dev.hにあるオブジェクト確保系の関数群において、自動的に 参照をスタックに積んでしまうことは可能です。ネイティブ関数実行後スタックを 戻す処理も、処理系側で苦もなくできます。 なぜ今そうなっていないかというと… うーん、何故なんでしょう? (^^; たとえば、オブジェクトを確保して、すぐに既存の配列の要素にセットする、 という場合、特にスタックに積む必要はないのでその辺の無駄を嫌ったような 気がしますが、現状の仕様は、「いつGCが起きる可能性があるか」という点について crowbarの内部実装をネイティブ関数の作者に晒していることになりますから、 大変よろしくないですね。次バージョンでは修正します。 ネイティブ関数側で、大量のオブジェクトの確保/破棄を繰り返すような処理が あるとすると、スタックが大量に無駄になりますが、そんなことわざわざ ネイティブ関数で書かないですよねえ… あるいはその場合でも、 ネイティブ関数用を呼び出したときのCRB_LocalEnvironmentに local referenceの表を持ち、スタックではなくそちらに参照を入れるようにして おけば、ネイティブ関数のプログラマに手で解放させることも不可能ではないですし。 >>ただ、たぶんこの場合、グローバル変数を共有して動かしたいのだと思います。 >>そうだとすれば、外部crowbarスクリプトのトップレベルを動かす方法は >>ありません。ただし、外部crowbarスクリプト中の関数であれば、 >>CRB_compile()とCRB_call_function()を使えば実行可能です。 > >外部crowbarスクリプト中の関数を呼べるということは、 >データを引数でC側からcrowbarの関数側にプッシュしてあげて、 >crowbarスクリプトのglobal変数に保存しておけば、 >データの共有はできると思います。 誤解させる書き方をしてしまったかもしれませんが、CRB_compile()と CRB_call_function()を使う方法なら、インタプリタを共有できますから、 グローバル変数によるデータ共有が可能です(まあ、引数で受け渡しするほうが よいのはよいでしょうけど)。 >私は、(ぱ)さんの本はほとんど持っていますが、もう少し内容を濃くして >「プログラミング言語を作る」もぜひ出版して欲しいです。 >早くていつ頃になりそうですか? いやあ、それはさっぱりわかりません。 まだ企画が動き出したわけですらないですし。
[この投稿を含むスレッドを表示] [この投稿を削除]
[697] Re:オブジェクト指向「初」入門
投稿者:(ぱ)
2007/02/20 02:13:25

>何が過剰なのかわからないのです。 [684]に書いたことを繰り返すつもりはありません。 >「クラス」も「スーパークラス」も、全く過剰だとは思えないので。 もはや日本語むちゃくちゃになっていませんか? 「スーパーサイヤ人に過剰な期待をするのはいかがなものか」 「悟空もベジータも、全く過剰とは思えない」 意味不明です。
[この投稿を含むスレッドを表示] [この投稿を削除]
[696] 昨晩は酔っ払ってました
投稿者:(ぱ)
2007/02/20 02:13:25

 えー、すみません、興味深い投稿がたくさんされてますが、昨晩は酔っ払って帰って きてそのまま寝てしまいました (^^;  お返事は今晩ということでよろしくお願いします。
[この投稿を含むスレッドを表示] [この投稿を削除]
[695] イテレータ(とCPS)
投稿者:NykR
2007/02/20 02:13:25

http://kmaebashi.com/programmer/devlang/regexp.html > Java流の、要素を取り出すだけで強制的にポインタを進めてしまう仕様は、 > ちょっとどうかと思うんですがねえ。 同感です。マージとかやりにくそう。 というわけでどちらか片方にするなら、GoFの方が良いな、と思ってたりするのですが、以下のような関数を用意すれば、GoF方式とJava方式の両方をあまり手間をかけずに作ることができます。(両方欲しい、という訳ではありませんが) function iterator_GoF(foreach_CPS) { this = new_object(); this.first = closure () { this.isDone = closure () { return false; }; foreach_CPS(closure (item, cont) { this.currentItem = closure () { return item; }; this.next = closure () { cont(null); }; }, closure (ret) { this.isDone = closure () { return true; }; }); }; this.first(); return this; } function iterator_Java(foreach_CPS) { this = new_object(); closure () { this.hasNext = closure () { return true; }; foreach_CPS(closure (item, cont) { this.next = closure () { cont(null); return item; }; }, closure (ret) { this.hasNext = closure () { return false; }; }); }(); return this; } function foreach(foreach_CPS, proc) { # ついでに作った foreach_CPS(closure (item, cont) { cont(proc(item)); }, closure (ret) {}); } # foreach_CPSは CPS(continuation passing style, 継続渡し形式)で書かれたforeachです。 # つhttp://www.shiro.dreamhost.com/scheme/docs/cont-j.html これらの関数に対し、コレクション側でforeach_CPSを用意して渡せば それぞれの関数に対応したイテレータが返されます。 例えば以下のような2分木があったとすれば tr = {13,{5,{3,{},{}},{13,{12,{},{}},{}}},{16,{16,{15,{},{}},{}},{17,{},{}}}}; function foreachTree_CPS(tree) { return closure (proc, fin) { closure internalIterate(node, cont) { if (node.size() == 0) { cont(null); } else { internalIterate(node[1], closure (ret) { proc(node[0], closure (ret) { internalIterate(node[2], cont); }); }); } }(tree, fin); }; } という関数を1つ定義するだけで print("foreach:"); foreach(foreachTree_CPS(tr), closure (item) { print(" " + item); }); print("\n"); print("GoF :"); for (i = iterator_GoF(foreachTree_CPS(tr)); !i.isDone(); i.next()) { print(" " + i.currentItem()); } print("\n"); print("Java :"); for (i = iterator_Java(foreachTree_CPS(tr)); i.hasNext();) { print(" " + i.next()); } print("\n"); のように、3種類のイテレータが使えてまあ便利。 でもシーケンシャルなコレクションだとそれほど嬉しくはありません。 CPSではforやwhileがまともに使えないので、例えば配列用のforeach_CPSは function foreachArray_CPS(array) { return closure (proc, fin) { closure loop(index, cont) { if (index == array.size()) { cont(null); } else { proc(array[index], closure (ret) { loop(index + 1, cont); }); } }(0, fin); }; } なんてことになって、要素数が多いとforeachに渡したときにクラッシュするなあ、とか、初期値と変数が遠いなあ、とか。 今の実装だと末尾再帰の最適化は物凄く大変そうですしね。 # でもこの形式のループは個人的にはむしろ欲しかったりします、crowbar ver.0.3.02にcall/ccを付けたので。ちなみに、この時点で末尾再帰の最適化はやりやすくなったのですが、CRB_Objectが増えたので先にGCを改造しなければならないのでした(どうでもいい報告)。 この手法は、 ・外部イテレータを直接作るのが難しくて ・ループによらないアクセスが簡単な データ構造(木とか) *では* 役に立ちます。 # ライブラリが簡単に書けます。というのはそれほど嬉しいことではない気がする
[この投稿を含むスレッドを表示] [この投稿を削除]
[694] Re:正規表現関連の関数の質問
投稿者:タイガー
2007/02/20 02:13:25

>LuaやJavaScriptの方法だと、名前空間が動的になるんですよね。 >環境作ってないので試してませんけど、Luaで「hoge = string」と書くと、 >hoge.sub()で文字列置換ができるようになるんじゃないでしょうか。 試してみたらできました。 静的、動的な違いというのも理解しました。 ありがとうございます。 >また、単なるテーブル(crowbarならオブジェクト)を名前空間に使うと、 >ライブラリ関数が壊せてしまうというのも、問題だと思います。 >Luaでは、string.subに代入できるんですよね? こちらも試してみたらできました。 確かに問題になりそうですね。 >と言いつつ、実は今crowbarに予約語finalを持ち込んで定数を作れるように >したりしてるので、ライブラリ関数のメンバとか名前空間オブジェクトをfinalに >してしまえば、これでもいい気がしてきました。うーん。 crowbarでfinalで定数作れるようにしてたんですね。 よくimmutableなクラスを作るときにはfinalにしないといけないと 書いてあるので、そういう意味ではfinalは必須な気もします。 Luaには定数にする方法はなかったような…。 >これは、Cの関数を抜けた後の話ですよね。レジストリに登録するという。 >crowbarでは、Cの関数の実行中でも、ヒープ関連の関数を呼び出すと >GCが動く可能性がありますから、ひとまずスタックに積まなければなりません。 私はよく分かっていないのですが、このcrowbarのアプローチは メジャーなのですか? >Luaの仮想スタックって、まさにcrowbarのスタックのような独自スタックでは? >crowbarのような手間がなさそうなところからして、Cの関数の部分だけ、 >Cスタックをスキャンするconservative GCなのかなあ、とも思ったのですが、 >テーブルを確保すると勝手にスタックに積まれること、他の参照型というと >文字列くらいですがCRB_Stringのような型では扱っていないことからして、 >コンサバGCではないようですね。 Luaの仮想スタックは、確かに独自スタックです。 しかし、私の知識不足とLuaのGCのメカニズムは記述がなかったため よく分かりません。 >うーん、CRB_add_native_function()は別にinterface.cの中で呼ぶ必要はないんですが >(実際今はnative.cとかの中で呼んでますし)。実行中でも呼べますから、 >ネイティブ関数内でも登録可能です。 実行中に呼べるのは応用範囲が広がりそうですね。 >これに近いことをするのであれば、(ver.0.4で新設された)CRB_create_closure()で >クロージャ作って、CRB_add_assoc_member()でオブジェクトに登録するなり >CRB_add_global_variable()でグローバル変数に登録するなりもできます。 crowbarのように実際のデータを直接扱えるとコードが分かりやすいと 思います。 Luaみたいに仮想スタック上にデータを作っておいて…みたいのは 分かりにくいです。 >crowbarスクリプトをまったく独立して動かせばよいのなら、インタプリタを >もうひとつ作って実行すればよいです。 >ただ、たぶんこの場合、グローバル変数を共有して動かしたいのだと思います。 >そうだとすれば、外部crowbarスクリプトのトップレベルを動かす方法は >ありません。ただし、外部crowbarスクリプト中の関数であれば、 >CRB_compile()とCRB_call_function()を使えば実行可能です。 外部crowbarスクリプト中の関数を呼べるということは、 データを引数でC側からcrowbarの関数側にプッシュしてあげて、 crowbarスクリプトのglobal変数に保存しておけば、 データの共有はできると思います。 C側に戻したいときもC側から渡す引数につめてあげれば 戻せます。 私は、この(例えば)Cとスクリプトとのデータの共有が一番 重要と思っているのですが、crowbarでも簡単にできそうですね。 だとすれば、既に組み込み言語として十分使えるレベルだと思います。 実は、Luaではこの一番重要な部分が一番面倒くさいです。 >やりたいこと・やるべきことはいろいろあって、その中にはcrowbar以外のことも >含まれます。もう少ししたら、crowbarほっぽりだして別の言語を作り始める >可能性も(かなり高い確率で)あります。企画の趣旨的には、crowbarを実用言語に >するよりも、バイトコードインタプリタのような違う実行形態の言語をもうひとつ >作る、という方が合っている気がしますし。 バイトコードインタプリタはかなり興味深いです。 楽しみにしています。 >ということで、crowbarに期待してくださるのは大変嬉しいことですし、 >私としても励みになるのですが、私の時間が有限である以上お応えできるかどうかは >わからない、ということで、すみませんがご理解ください。 私は、(ぱ)さんの本はほとんど持っていますが、もう少し内容を濃くして 「プログラミング言語を作る」もぜひ出版して欲しいです。 早くていつ頃になりそうですか? >あと、今だと鬼車のライセンス表記をどこかに含めなければいけませんよね。 >次バージョンで検討します。 ソースの理解は、まず動作が分かってからだと思うので、 とりあえず簡単に動かしてみたいという気持ちはあります。 あと、Cとの連携方法など、ユーザの視点でのcrowbarの使い方 みたいな文章も欲しいところです。 時間がないでしょうが、いつも楽しみにしていますので 頑張ってください。
[この投稿を含むスレッドを表示] [この投稿を削除]
[693] 多態性(ポリモーフィズム)について
投稿者:happie
2007/02/20 02:13:25

はじめまして。happieと申します。 以前、拙HPで勝手に(ぱ)さんのページを紹介させていただきました。 また『ポインタの完全制覇』や「疑り深いあなたのためのオブジェクト指向再入門」については、本質的なところを突いているため大変興味深く読ませていただきました。 オブジェクト指向の本質が、マルチプルインスタンスにあるということについても全く同意見です。 ところで、一部のオブジェクト論者の中には、ポリモーフィズムこそがオブジェクト指向の本質で、インターフェースでプログラミングすることが最も重要なことのように謳っています。実際、デザインパターンの解説書ではそのことがたびたび強調されています。 (ぱ)さんは、ポリモーフィズムに関してあまり記述がなかったように思いますが、どのようにお考えですか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[692] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

>>もっと言ってしまえば、「クラス」ではなくて「りんご」でも別に良かった…ということ? > >私は「術語に*過剰な*期待をするのはいかがなものか」と言っているのです。 >「術後にまったく期待するな」などと言った覚えはありません。 何が過剰なのかわからないのです。 「クラス」も「スーパークラス」も、全く過剰だとは思えないので。
[この投稿を含むスレッドを表示] [この投稿を削除]
[691] Re:正規表現関連の関数の質問
投稿者:(ぱ)
2007/02/20 02:13:25

>しかし、私はLuaの方法と、モジュールによる名前空間の分割の >本質的な違いを説明することはできません。 LuaやJavaScriptの方法だと、名前空間が動的になるんですよね。 環境作ってないので試してませんけど、Luaで「hoge = string」と書くと、 hoge.sub()で文字列置換ができるようになるんじゃないでしょうか。 Javaなどでもimportでパッケージ指定を省略できたりしますが、その規則は あくまで静的です。これを動的に変えられると、どこで何呼んでるんだか さっぱり、という状態になりそうな気がします。もっとも、 「そんなことしないでしょ」という考え方もありますが。 # でも、s = stringとかしてタイプ量を節約する人はいる気がする。 また、そういう規則では、統合開発環境はお手上げでしょうが、それは 形無し言語全般に言えることかも。 RDEとやらの入力保管機能はどうなってるんだろ、とマニュアルを見てみたら… ううむ。 http://rubyde.sourceforge.net/hiki/ja/Auto%2BComplete.html また、単なるテーブル(crowbarならオブジェクト)を名前空間に使うと、 ライブラリ関数が壊せてしまうというのも、問題だと思います。 Luaでは、string.subに代入できるんですよね? と言いつつ、実は今crowbarに予約語finalを持ち込んで定数を作れるように したりしてるので、ライブラリ関数のメンバとか名前空間オブジェクトをfinalに してしまえば、これでもいい気がしてきました。うーん。 >配列とハッシュが同列なら、配列リテラルがあるので、 >ハッシュリテラルも欲しいところです。 >初期化ができないと不便なので私は必須だと思っています。 ご意見ありがとうございます。 …と言いつつ、やりたいことは他にもあるので、すみませんが優先順位は高くないです。 >(2)に関しては、Luaは、GCされたくなければ、グローバルとして >別に残しておかなければなりません。 これは、Cの関数を抜けた後の話ですよね。レジストリに登録するという。 crowbarでは、Cの関数の実行中でも、ヒープ関連の関数を呼び出すと GCが動く可能性がありますから、ひとまずスタックに積まなければなりません。 >また、LuaがコンサバGCかどうかは不明ですが、 >crowbarのようなcrowbarスタックはLuaには、ないと思います。 Luaの仮想スタックって、まさにcrowbarのスタックのような独自スタックでは? crowbarのような手間がなさそうなところからして、Cの関数の部分だけ、 Cスタックをスキャンするconservative GCなのかなあ、とも思ったのですが、 テーブルを確保すると勝手にスタックに積まれること、他の参照型というと 文字列くらいですがCRB_Stringのような型では扱っていないことからして、 コンサバGCではないようですね。 >現状のCRB_add_native_function()で、ネイティブ関数を登録 >しておかなければならないのは、interface.cのソースを直接 >いじらないといけないので、これはLuaの方が楽だと思います。 うーん、CRB_add_native_function()は別にinterface.cの中で呼ぶ必要はないんですが (実際今はnative.cとかの中で呼んでますし)。実行中でも呼べますから、 ネイティブ関数内でも登録可能です。 >Cで書いた関数(例えば、l_sin()という関数)を、 >lua_pushcfunction(L, l_sin) >lua_setglobal(L, "mysin") >で、登録することによりLuaでmysin()という関数が使えます。 これに近いことをするのであれば、(ver.0.4で新設された)CRB_create_closure()で クロージャ作って、CRB_add_assoc_member()でオブジェクトに登録するなり CRB_add_global_variable()でグローバル変数に登録するなりもできます。 >また、Luaでは、CからLuaのコードを呼ぶ際に、 >Lを、lua_State型の変数とすると、 >lua_dofile(L, "test.lua") >により、test.luaが実行されるのですが、 >crowbarでは、これはどうやればできますか? crowbarスクリプトをまったく独立して動かせばよいのなら、インタプリタを もうひとつ作って実行すればよいです。 ただ、たぶんこの場合、グローバル変数を共有して動かしたいのだと思います。 そうだとすれば、外部crowbarスクリプトのトップレベルを動かす方法は ありません。ただし、外部crowbarスクリプト中の関数であれば、 CRB_compile()とCRB_call_function()を使えば実行可能です。 >ただのプログラミング練習言語で終わらせるのはもったいないと >思います。 >何か特徴を付けて、存在価値のある言語にして欲しいです。 やりたいこと・やるべきことはいろいろあって、その中にはcrowbar以外のことも 含まれます。もう少ししたら、crowbarほっぽりだして別の言語を作り始める 可能性も(かなり高い確率で)あります。企画の趣旨的には、crowbarを実用言語に するよりも、バイトコードインタプリタのような違う実行形態の言語をもうひとつ 作る、という方が合っている気がしますし。 ということで、crowbarに期待してくださるのは大変嬉しいことですし、 私としても励みになるのですが、私の時間が有限である以上お応えできるかどうかは わからない、ということで、すみませんがご理解ください。 >あと、できれば、Windows版のcrowbar.exeもダウンロード >できるようにして欲しいです。 確かに便利だと思いますし、今まで考えなかったわけでもないのですが、 企画の趣旨的にどうかという気もします。 あと、今だと鬼車のライセンス表記をどこかに含めなければいけませんよね。 次バージョンで検討します。
[この投稿を含むスレッドを表示] [この投稿を削除]
[690] Re:オブジェクト指向「初」入門
投稿者:(ぱ)
2007/02/20 02:13:25

>もっと言ってしまえば、「クラス」ではなくて「りんご」でも別に良かった…ということ? 私は「術語に*過剰な*期待をするのはいかがなものか」と言っているのです。 「術後にまったく期待するな」などと言った覚えはありません。 >例示が必要でしょうか? 「is-a」「汎化-特化」の考えは、まさに分類だと思うのですが(「汎化」「特化」という用語を誰が考えたかは知りませんが、いくらこれが術語だからと言って「低機能」「高機能」という意味でないのは明らかでしょう)。 そんな話をした覚えもありません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[689] Re:正規表現関連の関数の質問
投稿者:タイガー
2007/02/20 02:13:25

>ここを見る限り、stringというテーブルに、いろんなメソッドを >クロージャとして埋め込んでいる、という認識でよいでしょうか? その通りです。 私の表現は間違ってました。 stringテーブルにクロージャが入っているですね。 >ここでのstringの使われ方は、純粋に名前空間としてのものですよね。 >現状のcrowbarには、名前空間を分割する機能がないので、今回はreg_で >逃げたわけです。モジュールによる名前空間の分割はいずれそのうちやろうと >思っていますから、現時点で、Lua的な方法(crowbarでやるなら、グローバルな >stringというオブジェクトにクロージャを格納することになるのでしょう)で >解決しようとは思いません。 おっしゃる通り、名前空間と同じ仕組みです。 事実、Luaにはパッケージという概念がなく、テーブルにより パッケージを表現します。 しかし、私はLuaの方法と、モジュールによる名前空間の分割の 本質的な違いを説明することはできません。 しいて言えば、モジュールが一般的な意味のモジュールであれば、 文法を用意してあげることにより、ソースを見たときの 分かりやすさ(明確さ)は増すような気はします。 Javaみたいな感じだとpackageが名前空間を表していることが明確です。 Rubyのモジュールだと結局Luaと同じになるような気がします。 >crowbarの場合、スコープチェーンは「最上位の関数の中」までで止まっていますが、 >これをグローバルな領域まで広げ、グローバルな名前空間もassocで表現するようにして、 >グローバル変数もそのassocに、またグローバルな関数はクロージャとして >格納するようにすれば、名前空間の考え方が統一されるとともに、 >モジュールが欲しければトップレベルのオブジェクトをモジュールとして考えればよい、 >ということになります。実際JavaScriptはそんな感じになっています。 これもおっしゃる通りです。 Luaでは、グローバルなテーブルというものが、あらかじめ存在し、 stringなどは、その中に登録されています。 >ハッシュはですねえ… >もちろん考えていないことはないのですが、問題は、どの階層で実現するかです。 >言語の外で、ライブラリとして提供しても十分だと思うんですが、 >どうでしょうか(基本型のハッシュキーの取得方法は考えるにしても)。 >ハッシュのリテラル(「{"a" => "hoge"}」みたいなの)って要りますかねえ。 >考えるべきところはたぶんふたつあって、 私のイメージでは、配列(リスト)とハッシュは、同じ階層だと 思っています。 私の中で、リスト、ハッシュ、文字列は基本的なデータ構造だと 思います。 また、Luaでは、Table型により、配列とハッシュの両方を表現可能です。 >a)ハッシュのリテラルを言語仕様として用意するかどうか。 >b)ハッシュのオブジェクトを、(JavaScriptやLuaのように)現状のassocの > 別の見え方として考えるかどうか。 > >私としては、a)はまあやるならやってもいいけど(ただし優先順位は低い)、 >b)は嫌、というところです。 a)に関しては、 配列とハッシュが同列なら、配列リテラルがあるので、 ハッシュリテラルも欲しいところです。 初期化ができないと不便なので私は必須だと思っています。 b)に関しては、 assocの別の見え方にするというより、ハッシュを作り、 それでassocを表現するというイメージだと思いますが、 個人的には分けても統一化してもどちらでも良いと思います。 >ええと、私はLuaを使っていないのでご意見をお聞かせ願いたいわけですが、 >現状で、Luaとcrowbarを比べてみてどうでしょうか? >Luaとcrowbarでネイティブ関数を書くときのことを比較すると、 > >(1)引数や戻り値 > Lua…スタックを直接操作 > crowbar…引数や戻り値なので、ちょとはわかりやすいかな。 >(2)GC > Lua…何もしなくていい(?) Ruby的コンサバGC? >  lua_newtable()が「新しい空のテーブルを作り、スタックに積む。」そうだから、 >  スタックにないものは勝手にGCされそうな気もするんですが。 > crowbar…GCされたくなかったらスタックに積んどけ。 >  正直、これは面倒くさいです。せめて、最後のスタックの後始末を処理系側で >  やれば、というか実はそれは造作もないのですが。 >(3)アプリケーション固有データ > Lua…ユーザデータ > crowbar…ネイティブポインタ >  ファイナライザの仕様も含め、そっくりに見えます。また車輪を再設計したか。 (1)に関しては、crowbarの方は、CRB_Valueの構造が一度 分かってしまえば分かりやすいと思います。 Luaでは、常に目に見えない仮想スタックの状態がどうなっているかを 把握しておかないといけないのでかなり分かりづらいです。 (2)に関しては、Luaは、GCされたくなければ、グローバルとして 別に残しておかなければなりません。 また、LuaがコンサバGCかどうかは不明ですが、 crowbarのようなcrowbarスタックはLuaには、ないと思います。 (3)に関しては、Luaの方は、仮想スタック経由で扱うので 関数により抽象化されていて、 crowbarの方は、CRB_Valueで直接アクセスするので、 私個人の考えでは、crowbarの方が、何をやっているのかが 分かりやすいような気もします。 とにかくLuaでは常に仮想スタック経由なので、 そこら辺の仕組みが分かってしまえば良いのですが、 それがメリットなのかはまだ分かっていません。 >いっそ今みたいに特定の引数を持ったネイティブ関数が呼ばれる仕様ではなく、 >また、CRB_add_native_function()で関数を登録する必要もない、というようにして、 >もっと楽にネイティブ関数を書けるようにするというのも考えられますが… >処理系依存のコードはあんまり書きたくないですし。 現状のCRB_add_native_function()で、ネイティブ関数を登録 しておかなければならないのは、interface.cのソースを直接 いじらないといけないので、これはLuaの方が楽だと思います。 Luaでは、ライブラリとして登録するのは同様に面倒ですが、 ただLua側からC側の関数を呼びたいだけなら、 Cで書いた関数(例えば、l_sin()という関数)を、 lua_pushcfunction(L, l_sin) lua_setglobal(L, "mysin") で、登録することによりLuaでmysin()という関数が使えます。 このぐらいの手軽さがないと組み込みとは言えないと思います。 また、Luaでは、CからLuaのコードを呼ぶ際に、 Lを、lua_State型の変数とすると、 lua_dofile(L, "test.lua") により、test.luaが実行されるのですが、 crowbarでは、これはどうやればできますか? >まあ、別にRubyと張り合う気はないんですけど。 >方向性として、組み込み用スクリプトというのは、[685]にも書いたように >そもそも言語処理系に興味を持った時点からありました。 >ただ、今は別の方向も考えています。こんなの↓とか。 > >http://kmaebashi.com/zakki/zakki0027.html#lang ただのプログラミング練習言語で終わらせるのはもったいないと 思います。 何か特徴を付けて、存在価値のある言語にして欲しいです。 あと、できれば、Windows版のcrowbar.exeもダウンロード できるようにして欲しいです。 新しいバージョンをすぐテストしたいので。 よろしくお願いします。
[この投稿を含むスレッドを表示] [この投稿を削除]