K.Maebashi's BBS

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

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

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

[1278] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/21 00:40:14

>大文字小文字の例が悪かったのか、話がそこから進まないようです。 では、よい例を出してもらえませんか。具体的な例なしでこの手の話をしても 意味がありません。 774RRさんへの返信に >例えば総合試験で性能目標に達しなかった場合、従来の方法では普通は大変更に >なりますが、オブジェクト指向の場合、一部のクラスの取得処理を変更しただけで >修正できた例もあります。 とありますが、これも具体的にどういうケースだったのかわかりません。 普通に考えて、どこかの処理がボトルネックになっていたのなら、そこだけ 書き直せば速くなるでしょう。もちろん、その処理がプログラムのあっちこっちに コピペされていれば大変更になるでしょうが、関数等に切り出されて一箇所に まとめられていれば修正するのは一箇所です。ここまではオブジェクト指向は 関係ありません。 オブジェクト指向であったがゆえにうまくいった、とのことなので、 関数化ではうまくいかないケースだったのでしょう。どういう理由で、関数化では うまくいかず、オブジェクト指向(実装継承?)でうまくいったのでしょうか。 仕事のソースをここに貼ることができないのはわかっていますが、概要だけでも 教えてもらえませんか。興味深いので。 >遠くの所でnewした特有の処理の入ったクラスを、引数で使い回すのは、 >構造化のスタンプ結合的で、オブジェクト指向的には良くない設計です。 オブジェクト指向の最大の特徴のひとつであるポリモルフィズムは、遠いところで newしたオブジェクトのメソッドを呼ぶと、呼ぶ側が意識しなくても、 そのオブジェクトに応じたメソッドが呼び出される、というものですよね? デザインパターンなどでは生成に関するパターンだけでいくつもあって、 うちいくつかは、具体的なクラスが何であるかを意識させないようにするための ものですし、DI(Dependency Injection)なんかも考え方はそっち方面です。 まあ、この手のことは、当面用途もないのに調子に乗って柔軟性を求めると ソースが追えなくなってしまうので、私はあまり好きではないのですけれど。 ありがちな例では、たとえばログを出力するLoggerクラスをabstractクラスもしくは interfaceとして作って、それを継承またはimplementsしてファイルに吐くLoggerや syslogに吐くLoggerを作ったりしますが、これは、遠く離れたところでnewした Loggerを引数等で持って回ることになると思うんですが。 >オブジェクト指向の場合は処理は関連するデータと共にクラスに >まとめられるため、その引数を必要とするメソッドを、引数のクラス内 >に実装できるか検討すべきです。 意味がわかりません。 さっきのLoggerの例で言えば、Loggerクラスを引数として受け取るメソッドは Loggerを使うアプリケーションですが、アプリケーションのメソッドを Loggerクラスの中に作れ、という主張……ではないですよね。 >>ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの >>でしょうか。 こくぼさんからも質問が出ていますが、私もSEさんが「比較的マシ」だと思ってる 本やWebページを教えていただきたいです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1277] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/20 18:32:43

>ちなみにデザインパターンは学習する物ではなく、解析する物です。 ?? すみません、仰っておられる意味がわかりません…。 >これもひどい内容ですね。 詳しく教えていただきたいのですが、 どこがひどいと思われるのでしょうか? 「この当たりの話は知っています」と書かれていることから類似のWebページなどをご存知なのでしょうか。 できればその情報のソースを教えていただきたいです。 (自分的にこの手の情報はsumimさんの日記くらいしか知らないので) >これならまだ「ウィキペディア」の「オブジェクト指向プログラミング」の >方がマシです。 >一度読んでみてはいかがですか? ありがとうございます。 読んでみます。 #できれば他にもSEさんが比較的マシだと思ってる本やWebページを #いろいろ教えていただきたいところですが
[この投稿を含むスレッドを表示] [この投稿を削除]
[1276] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/20 15:47:40

>デザインパターンを学習されているなら継承を使う機会は減ると思うんですけど。 >#減るというか注意深くなるというか デザインパターンは知っています。 ちなみにデザインパターンは学習する物ではなく、解析する物です。 >ちなみにこのページはオブジェクト指向を学ぶうえにおいてとても参考になります。 >一読してみてください。 >http://d.hatena.ne.jp/sumim/20040525/p1 これもひどい内容ですね。 この当たりの話は知っていますが、参考にするのはまずいでしょう。 これならまだ「ウィキペディア」の「オブジェクト指向プログラミング」の 方がマシです。 一度読んでみてはいかがですか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1275] Re:疑い深い・・・
投稿者:SE
2009/05/20 15:31:59

>俺も (ぱ) 氏ももっとマクロな=大規模プログラムでの応用の話をしているわけです。 >そういうレベルでは、提示のコードのような派生はうまくいきません。 なぜ大規模プログラムでうまくいかないのかが分かりません。 実際、大規模プログラムで使用していますが、効果が出ています。 例えば総合試験で性能目標に達しなかった場合、従来の方法では普通は大変更に なりますが、オブジェクト指向の場合、一部のクラスの取得処理を変更しただけで 修正できた例もあります。 オブジェクト指向ではオブジェクト単位であるため、大きいレベルから小さいレベル まで対応できるのが特徴です。 >そもそも OO (というか継承-派生というシステム) のおいしいところは >・「基底クラスを使う人」と「派生クラスを作る人」が分離できる >・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい >・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、 > 自動的に正しく使ってもらえる、と判断してよい これが利点ですか?ちょっと他人に説明するのが難しいです。 私の例では、処理に大修正が入った場合(例えばDB変更や、ローカルファイルから 通信を使ったリモートファイルへの変更)、これだけの修正で済みますなどと 言えますが、上記の場合はどう説明しますか? >んで、マルチプルインスタンスの件のほうはもういいのでしょうか? >俺としては既に書いたとおり「対象読者層が異なる」というだけの話だと思っております。 了解しました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1274] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/20 14:40:28

スタックの例とかあんまり細かく見ずにコメントしますが…。 >それぞれ用途が違いますが、オブジェクト指向特有で強力なのが2,3です。 >別に全て2でやれと言っているわけではなく、2の使い方が出来るのが >利点だと言っている訳です。 >... >つまり、分かりやすいとか間違えやすいとか言う話は別として、 >4種類の変更方法を選択できるため、再利用性が高いと言っている訳です。 そもそも継承というメカニズムを使うのが間違いのもとになっちゃうような。 デザインパターンを学習されているなら継承を使う機会は減ると思うんですけど。 #減るというか注意深くなるというか >本は色々読みましたが、全てが同意できる物はありません。 となると、ここで力説されていらっしゃる実装継承を使ったOOP をどこから学ばれたのか興味深いですね。 ちなみにこのページはオブジェクト指向を学ぶうえにおいてとても参考になります。 一読してみてください。 http://d.hatena.ne.jp/sumim/20040525/p1
[この投稿を含むスレッドを表示] [この投稿を削除]
[1273] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/20 13:42:06

大文字小文字の例が悪かったのか、話がそこから進まないようです。 修正方法には以下の4つがあります。 ----------------------------------------------------------- 1.別名でメソッド追加  別々の処理として追加したい場合に使用 2.継承  関連処理をまとめて変更したい場合に使用 3.分割して親クラスを継承  関連処理をグループ化して、片方のグループを変更したい場合に使用 4.staticメソッドを作成  関連のない任意の場所で使用したい場合に使用 ----------------------------------------------------------- それぞれ用途が違いますが、オブジェクト指向特有で強力なのが2,3です。 別に全て2でやれと言っているわけではなく、2の使い方が出来るのが 利点だと言っている訳です。 間違いやすいとか分かりにくいと言うのは、実装者のスキルの話で、 よく見て追えば分かるし、変な設計をすれば分かりにくくなります。 遠くの所でnewした特有の処理の入ったクラスを、引数で使い回すのは、 構造化のスタンプ結合的で、オブジェクト指向的には良くない設計です。 オブジェクト指向の場合は処理は関連するデータと共にクラスに まとめられるため、その引数を必要とするメソッドを、引数のクラス内 に実装できるか検討すべきです。 つまり、分かりやすいとか間違えやすいとか言う話は別として、 4種類の変更方法を選択できるため、再利用性が高いと言っている訳です。 >ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの >でしょうか。 本は色々読みましたが、全てが同意できる物はありません。 殆どが、オブジェクト指向と言いつつ、デザインパターンの説明本や、UMLの説明本、 プログラミング言語の小技本、翻訳がおかしい本、中にはWEBアプリケーションの 作り方本もありました。 WEBサイトも同意できる物もあれば、出来ない物もあり、半々ぐらいです。 オブジェクト指向関係の書籍のひどさは、(ぱ)さんもご存じだと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1272] Re:疑い深い・・・
投稿者:774RR
2009/05/20 11:17:08

# 題名にハンドル入れるのやめてほしい > SE 氏 変えちゃいました # [1269] に返信してもよかったんだけどこっちにつなぐことにする [1269] > これを次のように変更します。1行で済みます。 ものすごく近視眼的コメントがついていて思わず苦笑してしまったのだけど、 *** そういう範囲でしか変更がありえない **** のであれば [1260] [1269] で提示のような修正もまぁあり、の範疇に収まります。 が、実世界においてはそういう局所な話ですまないことのほうが多く、 俺も (ぱ) 氏ももっとマクロな=大規模プログラムでの応用の話をしているわけです。 そういうレベルでは、提示のコードのような派生はうまくいきません。 そもそも OO (というか継承-派生というシステム) のおいしいところは ・「基底クラスを使う人」と「派生クラスを作る人」が分離できる ・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい ・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、  自動的に正しく使ってもらえる、と判断してよい という点にあるのであって、 決して「ソースの再利用のためのテクニック」ではないのです。 http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&thread=270 このへんとか。 基底クラスを使っている側にとって 基底クラス側が本来期待している挙動と異なる動きをするような派生クラス というのはまずいのです。 しかも、基底クラスユーザと派生クラス作者はたいてい別人なのです。 基底クラスを使うソースファイルと派生クラスを作るソースファイルも別ファイルなのです。 [あたかも便利そうに見える] [が、正しく設計されているとは必ずしも言い切れない] 派生クラスを安直に作り、使ってしまうと 異なる開発者がいて、複数のファイルから構成されていて、各プログラマは自分の担当範囲しか理解しきれない という大規模開発では見えにくい/直しにくいバグの元となります。 LSP (Liskov Substitution Principle) という概念も、この辺から来ています。 んで、マルチプルインスタンスの件のほうはもういいのでしょうか? 俺としては既に書いたとおり「対象読者層が異なる」というだけの話だと思っております。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1271] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/20 03:49:06

# どうもサーバの調子が悪いようで…… まずSEさんにお願いですが、投稿に返信を付ける際には各投稿の右上にある 「返信」リンクを使ってください。そうすることでスレッドがつながりますので [この投稿を含むスレッドを表示]をクリックすると関連する投稿をまとめて 読むことができます。 この掲示板の上のほうにある「スレッド順インデックス」をクリックすると、 他の投稿はちゃんとスレッドがつながっているのに、SEさんの投稿だけ 切り離されていることがわかるでしょう。 http://kmaebashi.com/bbs/thread.php?boardid=kmaebashibbs >>まあ、オセロの例で注記したように、マルチプロセスにはオブジェクト指向と似た面は >>ありますけど。「その論理で行くと」の「その論理」がどういう論理か、教えて >>いただきたいです。 >「マルチプルインスタンスがオブジェクト指向」と言う論理です。 >マルチプルインスタンスと言うのが何を指すのがよく分かりませんが、 >状態(内部の変数の値)の違う複数の処理群(クラス)と解釈しました。 「状態(内部の変数の値)の違う複数の"オブジェクト"」ですよね? まあ、クラスベースのオブジェクト指向ではオブジェクトの生成の雛形として クラスを使うわけで、「疑りぶかい~」ではクラスベースのオブジェクト指向の 話しかしていないわけですけれども。 実のところオブジェクト指向という用語は定義などないも同然なのですが、 「状態(内部の変数の値)の違う複数の"オブジェクト"を持てること」が たいていのオブジェクト指向の定義の必要条件である、ぐらいのことはたぶん 言ってもよいでしょう。 で、そうするとなぜ「マルチプロセスやマルチスレッドはオブジェクト指向になる」 のですか? 「DOSを乗っけたPCを2台もってこれば同時に複数のプログラムを動かせるので、 DOSはマルチプロセスだ!」という主張は誰もしないと思いますけど。 >>・Stackが引数かなにかで渡されたとき、本家StackなのかUpperStackなのかわからなくて危険。 >引数の型を見れば分かると思います。 void hoge(Stack s) { …… } というメソッドがあったとき、sがStackなのかUpperStackなのかは 「わからない」と思いますが? >>・別の誰かがLowerStackを作ったら、いつかマージするの? >もし別機能として作るなら、Stackを継承してLowerStackを作ります。 >例えば大文字にした後に先頭に0を付加するような、UpperStackの処理結果に追加する物なら、 >UpperStackを継承して作ります。 >すでにLowerStackが出来てしまっているならマージしません。 で、同一インスタンスのスタックに放り込んだデータについて、ある場所では 大文字で取り出したいし、ある場所では小文字で取り出したい、という場合、 どのクラスを使えばよいのですか? >>「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」 >>ということにしたいのでしょうか? >そうです。 だとすれば比較対象にget(boolean up)を持ってきているのはおかしいですね。 get(boolean up)を使う人は、大文字が欲しいとき、意識して引数にtrueを 渡さなければならないからです。 774RRさんへの返信に >ダウンキャストでなく、newするときに新しいクラスを使うと考えてください。 とありますが、(かなり離れた場所でnewされたかもしれない)Stackが UpperStackなのかStackなのかを意識しなければ、UpperStackのget()を 便利に使うことはできません。SEさんの主張は矛盾しています。 >>この改修により、プログラムにUpperStackという「異物」が実行時に紛れ込むわけで、 >>「Stackにputしたんだから、当然同じものがgetできるだろう」と思い込んでいる >>既存コード(Stackそのものを含む)にはおもいっきり影響を与えます。 >既存コードはソースに手を入れないので、影響はないと思いますが。 既存コードに引数でUpperStackを渡したら、入れたものを勝手に大文字に 変換するおかしなStackが紛れ込むことになります。ここではそういうことを 書いています。 >もう少し分かりやすい例をあげます。 Javaのコレクションクラスライブラリは、StackがVectorを継承していたりして いろいろトホホなので、「良い例」として出せるものではないと思います。 現実的に許容範囲内の例ではあるかもしれませんけど。 で、LinkedHashMapやTreeMapですが、これらがHashMapを継承してしまったために、 ・同じコレクションに対し、ある時は入力順に表示したいし、ある時は ソートして表示したい、という場合どうすればよいのか? (要件としてはすごくありそうだと思いますけれども) ・サブクラスにアクセスさせるために、HashMapのフィールドであるtableが  パッケージアクセスになってしまっているがこれはカプセル化の破壊では  ないのか。 (protectedにしなかったのはSunのエンジニアの良識だと思います) ・ていうかLikedHashMapではaddEntryとかcreateEntryとかパッケージアクセスの メソッドをばんばんオーバーライドしているけれど大丈夫か(スーパークラスの 実装に強く依存している)。 といった問題があるわけです。 それでもまあなんとか「現実的に許容範囲」なのは、オーバーライドした メソッドが、スーパークラス側のメソッドに対し「最低限同等の責務を果たす」と いうオーバーライドにおける大原則を守っているからでしょう。 その点においてもSEさんのUpperStackはだめです。同じget()でありながら、 勝手に大文字に変換してしまうためです。 で、 >Map<String, String> mp = new LinkedHashMap<String, String>(); ここでMapに代入しているのはなぜですか? 入力順に出てくることを期待するのなら、LinkedHashMapのまま持ち歩くほうが 安全です。あるMapがLinkedHashMapのつもりだったのに実はそうでなかった、 というケースは、プログラムが大きくなって、newする場所と使う場所が離れれば 離れるほどいくらでも発生することです。そうなってしまえば、入力順に 取り出せないのですから致命的な上、コンパイルエラーどころか実行時のエラーも出ず、 黙って間違った順番でデータを吐き続けることになります。 これを避けるには、ダウンキャストするか、instanceofでクラスを確認する 必要があるでしょう。危険ですけれども。774RRさんがおっしゃっているのは そういうことです。 Mapに代入するメリットと言えば、たとえばMapの中身をダンプする void dumpMap(Map m);というメソッドに対し、LinkedHashMapを渡せば 入力順に表示されるしTreeMapを渡せばソートして表示される、という動きを 期待したいときでしょう。でもこれは、dumpMap()という既存メソッドに 新たに開発したオブジェクトを混入させることに他ならず、それでうまく 動くかどうかは保証の限りではありません。『「異物」が実行時に紛れ込む』と 書いたのはそういうことです。 # これをうまく動かすためには、やはり先ほどの「オーバーライドにおける大原則」 # を守る必要があるわけです。 で、 >ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの >でしょうか。 これについては答えていただけないのでしょうか。ぜひ書名を教えて欲しいのですけれども。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1270] >(ぱ)こと管理人さん
投稿者:SE
2009/05/19 16:21:52

>まあ、オセロの例で注記したように、マルチプロセスにはオブジェクト指向と似た面は >ありますけど。「その論理で行くと」の「その論理」がどういう論理か、教えて >いただきたいです。 「マルチプルインスタンスがオブジェクト指向」と言う論理です。 マルチプルインスタンスと言うのが何を指すのがよく分かりませんが、 状態(内部の変数の値)の違う複数の処理群(クラス)と解釈しました。 >そこでわざわざ継承してクラスを作ったって、以下のような問題が起きるだけです。 >・Stackが引数かなにかで渡されたとき、本家StackなのかUpperStackなのかわからなくて危険。 引数の型を見れば分かると思います。 >・別の誰かがLowerStackを作ったら、いつかマージするの? もし別機能として作るなら、Stackを継承してLowerStackを作ります。 例えば大文字にした後に先頭に0を付加するような、UpperStackの処理結果に追加する物なら、 UpperStackを継承して作ります。 すでにLowerStackが出来てしまっているならマージしません。 >「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」 >ということにしたいのでしょうか? そうです。 >この改修により、プログラムにUpperStackという「異物」が実行時に紛れ込むわけで、 >「Stackにputしたんだから、当然同じものがgetできるだろう」と思い込んでいる >既存コード(Stackそのものを含む)にはおもいっきり影響を与えます。 既存コードはソースに手を入れないので、影響はないと思いますが。 新たに作るコードはどちらを使うか意識する必要はありますが。 >上のほうで『実のところ「要素を大文字に変換して返すスタック」がどんな時に >役に立つのか想像できません』と書きましたが、結城浩さんが「例は嘘をつかない」 >と書いておられるように、こういうところで現実のプログラムに即した適切な例が >出てこないなら、おそらくそれは考え方のほうが間違っています。 もう少し分かりやすい例をあげます。 --------------------------------------------------------------------- Map<String, String> mp = new HashMap<String, String>(); mp.put("aa", "11"); mp.put("cc", "33"); mp.put("bb", "22"); for(String key : mp.keySet()){   System.out.println(key); } --------------------------------------------------------------------- 入力した順番に表示したい場合 --------------------------------------------------------------------- Map<String, String> mp = new LinkedHashMap<String, String>(); mp.put("aa", "11"); mp.put("cc", "33"); mp.put("bb", "22"); for(String key : mp.keySet()){   System.out.println(key); } --------------------------------------------------------------------- ソート表示したい場合 --------------------------------------------------------------------- Map<String, String> mp = new TreeMap<String, String>(); mp.put("aa", "11"); mp.put("cc", "33"); mp.put("bb", "22"); for(String key : mp.keySet()){   System.out.println(key); } ---------------------------------------------------------------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1269] >774RRさん
投稿者:SE
2009/05/19 15:22:44

>あえて言わせていただくと、提示例はやっちゃダメな「実装継承」の典型例であって >俺の後輩君がこんなコードかいてたら0点つけるですよ。 大文字変換は何かしらの処理の例として出したので、getで何かの処理を行った結果を返すと考えてください。 >これは、実体が Stack であるインスタンスに対して UpperStack にダウンキャストして使う、としか読めない。 >そんな危険なことをさせるわけにはいかないと思うのだが。 ダウンキャストでなく、newするときに新しいクラスを使うと考えてください。 --------------------------------------------------------------------- Stack st = new Stack(); st.put("aa"); st.put("bb"); st.put("cc"); System.out.println(st.get()); System.out.println(st.get()); System.out.println(st.get()); --------------------------------------------------------------------- これを次のように変更します。1行で済みます。 --------------------------------------------------------------------- UpperStack st = new UpperStack(); st.put("aa"); st.put("bb"); st.put("cc"); System.out.println(st.get()); System.out.println(st.get()); System.out.println(st.get()); ---------------------------------------------------------------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1268] Re:状況その4
投稿者:
2009/05/18 20:59:24

Kmyaccを使用していましたが、エラー復帰がうまくいかず。1回の構文エラーで yaccが終了してしまう問題を抱えてしまいました。いろいろ調査したが、どう にも情報が見つからなかったため、Bisonに変更。問題なくエラー処理および エラー復帰が出来るようになりました。堅牢なシステムへまた1歩です。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1267] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:
2009/05/18 18:28:11

>これなんですが、C++だと、privateなメンバ変数とかは、外から参照すれば >コンパイラにエラーで怒られるとはいうものの、.hファイル中には記述されて >しまいますよね。  カプセル化という言葉に対して、きっちりとした完全な意味を求めてるのだ ろうと思いますが、私はそこまでのことを意識してこの言葉を使っていません。 問題は。  必要なこと意外一切情報を出さないほうがいいのか。内部がある程度想像 できるほうがいいのか?Cはたとえ使えなくともクラスのデータやメソッドが見 える。これが良いか悪いかでしょう。私は後者のほうが気分的には良いです。 使わない情報が見えたとしても、実質的にカプセル化されていれば問題ないと 考えます。  言語の設計において、理想的なものを作っていくのもあります。私の場合は 目的が実現できれば簡単なものでいいと思って設計しています。その代表が #defineです。古い仕様で問題点も内包しますが、実に使いやすく融通が利きます。 今では#defineはあまり良くないとされていますが、私は利点を選びました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1266] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:(ぱ)こと管理人
2009/05/17 20:50:06

> 私にとってOOPを使う最大の理由は。 > > 「カプセル化により見透視のよさ!」これに尽きます。 これなんですが、C++だと、privateなメンバ変数とかは、外から参照すれば コンパイラにエラーで怒られるとはいうものの、.hファイル中には記述されて しまいますよね。Javaだとメソッドの実装も書くことになるのでもっと深刻です。 これでは利用者側の再コンパイルが必要になりますし、ライブラリの実装が 終わる前にアプリケーションを作り始めたいという場合にも困る、ということで、 (Javaで言えば)インタフェースのみ公開してHogeImplみたいなクラスを作る、 なんてパターンが知られています。 私にはこれは必須に思えるので、Diksamではもうちょっと言語で積極的に サポートしたかったんですけどね。うまい文法が思いつかずにJavaと同等に なってしまっています。うーん、いつかそのうち。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1265] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:(ぱ)こと管理人
2009/05/16 22:40:50

>その論理で行くと、マルチプロセスやマルチスレッドはオブジェクト指向になると >思いますが、 ならないと思いますが…… まあ、オセロの例で注記したように、マルチプロセスにはオブジェクト指向と似た面は ありますけど。「その論理で行くと」の「その論理」がどういう論理か、教えて いただきたいです。 >例えばこれを修正して、大文字に変換して返す物を使いたいとします。 >----------------------------------------------------------- >public class UpperStack extends Stack { >  public String get(){ >    return super.get().toUpperCase(); >  } >} >----------------------------------------------------------- 774RRさんがすでに書いていますけど、これは典型的な「ダメな実装継承の例」でしょう。 # 「実装継承」でGoogleしてみることをお勧めします。 実のところ「要素を大文字に変換して返すスタック」がどんな時に役に立つのか 想像できませんが、それはまあ、「あくまで例だから」ということにしても、 このケースは、 「要素をgetする側は、大文字が欲しいとき、そのことを意識している」 のでしょうか。 意識しているのであれば、そもそも「stack.get().toUpperCase();」で済む話です。 大文字に変換する、という単純な処理でないのなら、ユーティリティメソッドを 作ればよいでしょう。 そこでわざわざ継承してクラスを作ったって、以下のような問題が起きるだけです。 ・Stackが引数かなにかで渡されたとき、本家StackなのかUpperStackなのか  わからなくて危険。 ・別の誰かがLowerStackを作ったら、いつかマージするの? ・ユーティリティメソッドではprivateメンバにアクセスできないが、  継承なら、protectedにしておけばサブクラスからアクセスできる、というのが  趣旨なら、それはカプセル化の破壊以外の何者でもない。 ところで、SEさんの例では、get()メソッドがオーバーライドされています。 「要素をgetする側は、大文字が欲しいとき、そのことを意識している」のであれば、 仮に継承を使うとしても、getUpper()メソッドをつけることでしょう。 オーバーライドしているということは、 「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」 ということにしたいのでしょうか? # それにしては、get(boolean up)と対比しているのでよくわかりませんが。 もしそうなら、 >そのため、変更により以前の機能のまま使用したい場所には影響がありません。 というわけにはいきません。 この改修により、プログラムにUpperStackという「異物」が実行時に紛れ込むわけで、 「Stackにputしたんだから、当然同じものがgetできるだろう」と思い込んでいる 既存コード(Stackそのものを含む)にはおもいっきり影響を与えます。 しかも、get(boolean up)とは違い、実際に動かしてみなければ検出できない バグになりますからさらにタチが悪いです。 上のほうで『実のところ「要素を大文字に変換して返すスタック」がどんな時に 役に立つのか想像できません』と書きましたが、結城浩さんが「例は嘘をつかない」 と書いておられるように、こういうところで現実のプログラムに即した適切な例が 出てこないなら、おそらくそれは考え方のほうが間違っています。 ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの でしょうか。 いまどきこんなバリバリの実装継承でオブジェクト指向を説明している教科書は そうそうないと思っていたので、もし新しい本にそういうことが書いてあったのなら 興味があります。ぜひ書名を教えてください。 ところで、私が現在作っているクラスベースオブジェクト指向言語Diksamでは、 「concreteクラスは継承できない」ということにしてしまっています。これは 実装の手抜きではなく、意図して行っています。 ここまでやってしまうと異論はあるかもしれませんが、Effective Javaとか GoFのデザパタ本とかで、かなり昔から、散々「抽象クラス以外は継承するな」と 言われてますし、SEさんのような誤解を防止するためにもこの方がよいのではないかと。 http://java-house.jp/ml/archive/j-h-b/050862.html
[この投稿を含むスレッドを表示] [この投稿を削除]
[1264] [業務連絡]掲示板が復旧したようです
投稿者:(ぱ)こと管理人
2009/05/16 21:47:05

原因は不明ですが、しばらくこの掲示板が投稿できない状態になっていました。 閲覧は通常通り可能でしたが、送信ボタンを押してもプレビュー画面に遷移しない、という状態でした。 それでしばらくテスト掲示板で様子を見ていましたが、どうも直ったようです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1263] 状況その3
投稿者:
2009/05/15 18:56:21

 yacc,lecの修正とプリプロセッサの作成が終わりました。ファイルの多重#includeと 多重の#define宣言を処理できるようになりました。  次の3つのファイルをt001.dkmで起動すると。 --ファイルt001.dkm--------------------------- // aaaaaaaa #include "t001-01.dkm" #define DEF1 DEF2 + "def1 " // aa int main() { string str; str = DEF1; str = DEF2; str = DEF3; } --ファイルt001-01.dkm------------------------ //ssssssssssss #define DEF2 DEF3 + "def2 " // bb #include "t001-02.dkm" //aaaa int print (string str); --ファイルt001-02.dkm------------------------ //ssssssssssss #define DEF3 "def3 " // cc int printnl(string str) { print(str + "\n"); } -------------------------------------   ↓  プリプロセッサ   ↓ ------------------------------------- int printnl (string str ) { print (str +"\n"); } int print (string str ); int main () { string str ; str ="def3 "+"def2 "+"def1 " ; str ="def3 "+"def2 " ; str ="def3 " ; } -------------------------------------  になってコンパイラに渡されます。もちろんメモリ渡し、エラーもファイル名+行番号で出さ れます。コメントやインデントは内部的に不要なので無くなっています。  最上位の制御構造がマルチスレッドを意識した構造を作りこみ、コンパイラは単独で動作する 構造になりつつあります。ジェネレータは関数単位で実行される予定です。  これでようやく中断前に戻れます。  関数のリンクは総て動的リンクにする予定です。最初の1回だけ動的リンクが行われ、その後 コンパイラが起動されるか、中間コードが破棄された時のみ再度動的リンク試験が行われます。 これでほとんどの関数コールは、直接起動されることになり。スピード的に問題ないと思って います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1262] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:
2009/05/15 18:53:09

 私にとってOOPを使う最大の理由は。  「カプセル化により見透視のよさ!」これに尽きます。  継承や多態化はそのサポートのために。再利用性は設計の問題であり。OOとは 関係が薄い場合がある。ただし、OOを使っても見透視の悪いコードはいくらでも かける。が、よく整理されたクラスの見透視の良さは、OOが無い言語に比べて 格段にいい。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1261] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:774RR
2009/05/15 14:56:25

「再入門」のそのあたりの記述は、そもそも「インスタンスが複数あっていい」というあたりを理解していないプログラマ向けの文書。 SE氏の指摘は「インスタンスが複数あるのは当たり前」と理解しているプログラマの視点なわけで。 そういう意味で、対象読者層が異なるだけのことだと思う。 あえて言わせていただくと、提示例はやっちゃダメな「実装継承」の典型例であって 俺の後輩君がこんなコードかいてたら0点つけるですよ。 > そして、大文字で取得したい場所では、このUpperStackを使うようにします。 これは、実体が Stack であるインスタンスに対して UpperStack にダウンキャストして使う、としか読めない。 そんな危険なことをさせるわけにはいかないと思うのだが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1260] 疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:SE
2009/05/15 14:06:45

疑りぶかいあなたのための「オブジェクト指向再入門」を読みました。 部分的に同意できる所もありますが、オブジェクト指向の「本質」はマルチプル インスタンスだと言うのは全く違うと思います。 その論理で行くと、マルチプロセスやマルチスレッドはオブジェクト指向になると 思いますが、これらはオブジェクト指向云々以前から存在する、別の話だと思います。 オブジェクト指向プログラミングの利点は、 「変更がしやすい」事と「変更しても以前の機能が失われない」事です。 簡単に説明します。 先入れ後出し形式のデータ(スタック)をクラス化したとします。 エラー処理を考慮しなければ、大体以下のようになるでしょう。 ----------------------------------------------------------- public class Stack {   private String[] data = new String[100];   private int index = 0;   public Stack(){   }   public void put(String val){     data[index] = new String(val);     index++;   }   public String get(){     String ret = "";     index--;     ret = data[index];     return ret;   } } ----------------------------------------------------------- 例えばこれを修正して、大文字に変換して返す物を使いたいとします。 ----------------------------------------------------------- public class UpperStack extends Stack {   public String get(){     return super.get().toUpperCase();   } } ----------------------------------------------------------- そして、大文字で取得したい場所では、このUpperStackを使うようにします。 ここで重要なのは、基のクラスのStackには全く修正が入らない事です。 そのため、変更により以前の機能のまま使用したい場所には影響がありません。 ちなみに、Stackに別名の大文字で返すメソッドを追加すると言う方法もありますが、 基のソースに修正が入るため、デグレートの危険が発生します。 やたらに継承をしたくない場合は、それでも構いませんが、以下の方式はダメです。 ----------------------------------------------------------- public class Stack {   private String[] data = new String[100];   private int index = 0;   public Stack(){   }   public void put(String val){     data[index] = new String(val);     index++;   }   public String get(boolean up){     String ret = "";     index--;     if(up){       ret = data[index].toUpperCase();     }else{       ret = data[index];     }     return ret;   } } ----------------------------------------------------------- なぜダメかは、構造化プログラミングを行っていて、度重なる修正で スパゲッティープログラム化しているのを見た事のある人なら分かるでしょう。 これを使用している所で、変更の必要ない既存部分にも手が入り、処理にも分岐が 入って複雑化するためです。 適切にオブジェクト指向プログラミングされていれば、修正が入っても劣化せず、 むしろ抽象化され使いやすいクラスになっていきます。 オブジェクト指向プログラミングの目的はこれだけです。 カプセル化、継承や多態化もこれを実現するための手段に過ぎません。 そのため「オブジェクト指向の目的は、再利用性を高める事」は正しいです。 しかしこの場合の再利用性は、関数化などの話ではなく、変更の時の使いやすさを 指しています。 新人が誤解するので「オブジェクト指向はマルチプルインスタンス」と言う記述は 修正か注意書きをしてほしいです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1259] Re:状況(日記?)
投稿者:(ぱ)こと管理人
2009/05/12 02:16:16

>> 見間違いかもしれないけど、0.2.0はメモリーストレージを使ってないような・・・ >見間違いかと思います (^^; >了解しました、構文解析の所を今見た所確かにそうです。失礼いたしました。 >しかし、以前メモリートラブルでと話したとき、いつもmallocの中でこけてた >んです。 補足ですが、構文解析部分はMEM_Storageを使用してまとめて開放していますが、 コンパイルにより作られるDVM_Executableは各オブジェクトを個々にMEM_malloc()して 作っています。こちらは、配列のオーバーランなどすると、次のmalloc()で こける可能性が高いと思います(いまどきはそうでもないかも)。 malloc()で確保した領域を配列のオーバーランで壊したことを検出するために、 MEMではアプリケーションに渡す領域の前後を0xCDで埋めていて、これをチェックする 関数MEM_check_all_blocks()を用意しています。実際これでバグを見つけたことも 多いのですが、最近はLinux環境ではとっととvalgrindを使っていたりします。 Windowsで、フリーなvalgrind相当品があるかどうかは不勉強にて知りません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1257] Re:状況(日記?)
投稿者:
2009/05/10 23:54:32

>見間違いかと思います (^^; 了解しました、構文解析の所を今見た所確かにそうです。失礼いたしました。 しかし、以前メモリートラブルでと話したとき、いつもmallocの中でこけてた んです。それで思い違いをしたかな、結局追いきれなくてあきらめたんですけ ど。いや、相当粘ったんですよこれでも… >fix_tree.cでは主にTypeSpecifierを解析木に付加しますが、おっしゃるとおり、 >たとえばある式がintのTypeSpecifierを持っていて、それにマイナス演算子を適用した >このへんのことは以下にちょっとだけ書いてありました。 了解しました、と言うかまとめて開放だから無問題です。単に私がちょっとfixtree で手間取ったのが、それが理由だったんです。結局、メモリー監視デバックルーチ ンが、shared_ptrのような機能を持ってメモリー管理になってしまいましたんです。 もともとスマートポインターは重いからやめようと思ってた矢先の出来事で。 ええ、Boostのpoolに変えます… >「一番外側のブロック」ではなく、その名のとおり「現在のブロック」です。 了解しました。実はコメントを書き換えなおすの忘れてた。昔のままだった。 何も考えずに、有るのそのままコピペしてました。 >> ST_MemberExpression member_expression; // 使用していない? >クラスを導入していないver.0.2では確かに使っていませんね。 了解しました。ありがとうございます。これなんだろう?調べなきゃと思っていました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1256] Re:状況(日記?)
投稿者:(ぱ)こと管理人
2009/05/10 19:05:32

> 見間違いかもしれないけど、0.2.0はメモリーストレージを使ってないような・・・ 見間違いかと思います (^^; create.cで解析木のノードを確保する際も、fix_tree.cで主にTypeSpecifierを 確保する際も、最終的にはdkc_malloc()を呼んでいますし、dkc_malloc()は コンパイラが保持してるMEM_Storageを使用してメモリ確保しています。 http://kmaebashi.com/programmer/devlang/diksam_src_0_2/S/11.html#22 > 実は、構文解析で構文ツリーが出来た時点では、TOPのCT_Compilerのオブジェクトを >deleteすればディストラクタ繋がりできれいに総てのメモリーを解放できたのですが >Fixtreeを作ってみると、多重リンクはするはリンクが切れてフリーが山ほど出てくる >はで。 fix_tree.cでは主にTypeSpecifierを解析木に付加しますが、おっしゃるとおり、 たとえばある式がintのTypeSpecifierを持っていて、それにマイナス演算子を適用した ような場合には、マイナス演算子の式のTypeSpecifierは、その子ノードのものを 直接使用していたはずです(多重リンク)。また、[]演算子を適用するとTypeDeriveが 1段階外されますが、この時、[]演算子のノードのTypeSpecifierは、TypeDeriveの 連結リストの途中のノードを指します(その下のノードでは根元を参照していますが)。 このへんのことは以下にちょっとだけ書いてありました。 http://kmaebashi.com/programmer/devlang/diksam_0_1_comp.html | コンパイル時のTypeSpecifierは、なにしろ解析木のすべての式のノードに | 割り当てられます。たとえば「a + 1」という式がありaがint型の時、 | intを表現するためのTypeSpecifierが(「a」と「1」と「a + 1」のために) | (現状の実装では)3つ確保されています。でもよく考えれば「a + 1」のノードの | TypeSpecifier は左辺か右辺かどっちかのを直接参照してもよいはずで、 | 実際マイナス演算子ではそうしています。 | このように、TypeSpecifier構造体は、誰が所有者なのかわけがわからんような | こんがらがった参照で保持されているので、解析木の他の部分同様、 | コンパイル終了時に(MEM_Storageの機能を使用して)一括で破棄しています。 >class CT_Compiler : public CBase >{ >public: > CT_Block * current_block; // 一番外側のブロック 微妙に気になるのですが、current_blockは、少なくとも元のソースでは、 「一番外側のブロック」ではなく、その名のとおり「現在のブロック」です。 create.cにおいてBlockを生成する際に、親のブロックへの参照をセットするために 使用しています。 >class CT_Expression : public CBase >{ ... > union { > ST_MemberExpression member_expression; //    使用していない? これは、オブジェクトのメンバを参照するためのノードですが、 クラスを導入していないver.0.2では確かに使っていませんね。 ていうかソースには一応入っていたことに私の方が驚きました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1255] Re:状況(日記?)
投稿者:
2009/05/09 22:51:48

お疲れ様です。返事をもらえると嬉しいのですが、ごゆっくりどうぞ。  ↓のクラスを見てわかるとおりに、ほとんどstructをクラスにしたままです。内部 データが少し変わっていますが、structの全体接続構造はほとんどそのままです。  私も意味もなくポリモルフィズムするのは好きではないし。本来の目的は クラスでパッキングして見通しを良くしよう。そして、書くことによる自身の 理解、そして必要機能の追加のためです。それと、diksamもほぼ同じ量のメモリー 確保をしていますよ。  見間違いかもしれないけど、0.2.0はメモリーストレージを使ってないような・・・ class CT_Compiler : public CBase { public: int function_count; // 関数の数 CT_FunctionDefinition * function_list; // 関数のリスト CT_DeclarationList * declaration_list; // トップの宣言リスト CT_StatementList * statement_list; // トップのステートメントのリスト CT_Block * current_block; // 一番外側のブロック //== 式のツリーノード =========================================== class CT_Expression : public CBase { public: CT_TypeSpecifier *type; // E_ExpressionKind kind; // 式の種類 int line_number; union { E_Boolean boolean_value; // boolデータ リテラル int int_value; // intデータ リテラル double double_value; // doubeデータ リテラル string *string_value; // stringデータ リテラル ST_IdentifierExpression identifier; // 関数又は宣言文の識別子 ST_CommaExpression comma; // カンマ(,)式 ST_AssignExpression assign_expression; // 代入式 ST_BinaryExpression binary_expression; // 演算式 CT_Expression *minus_expression; // マイナス式 CT_Expression *logical_not; // 論理否定式 ST_FunctionCallExpression function_call_expression; // 関数式 ST_MemberExpression member_expression; //    使用していない? CT_ExpressionList *array_literal; // 配列データ リテラル ST_IndexExpression index_expression; // 配列の添え字式 ST_IncrementOrDecrement inc_dec; // ++,--,式 ST_CastExpression cast; // キャスト演算式 ST_ArrayCreation array_creation; // 配列生成式 } u;  実は、構文解析で構文ツリーが出来た時点では、TOPのCT_Compilerのオブジェクトを deleteすればディストラクタ繋がりできれいに総てのメモリーを解放できたのですが Fixtreeを作ってみると、多重リンクはするはリンクが切れてフリーが山ほど出てくる はで。メモリー監視・チェック・報告のデバックプログラムが、一躍メモリー管理 プログラムに昇格して、多重リンクや放置されたメモリーを管理して、きれいに掃除 することになりました。思わぬ副作用が・・・  今大改造中で動かせなかったのですが、構文解析時点で5千数百のnewをしていました。  実は、ジェネレータとVM部分を始めていたのですが、ほしい仕様のための変更部分が 目立って見えてきたため、yacc,lex部分から大きく改造を始めてしまいました。 いま、#include #define 構文の追加と最外枠のステートメント禁止、main()関数起動 を組み込み始めました。そして上の二つの構文のためにプリプロセッサを書いています。 だから、コンパイルは+1増えて4ステージになりました。#includeは単に外部ファイルを 同一ファイルとしてコンパイルできる普通の機能です。でも、その為にライン数管理が ファイル名+ライン数になってその部分が全体的改造に。  本当は、一通り終わるまで新機能は入れないつもりでしたが、チョコチョコ変えている 時点で、もう全体変更しようと思ってしまった。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1254] Re:状況(日記?)
投稿者:(ぱ)こと管理人
2009/05/09 02:35:53

世間では連休で私も会社は休みだったはずですが何かとどたばたしてまして お返事が遅れましてすみません。 > ちなみに、test.dkmで最高6800ぐらいnewします。 これで速度低下しないかと心配して、crowbarやDiksamではMEMモジュールを作って MEM_storage_malloc()を使ったのですが、C++でクラスを使おうとすると単純に 置き換えはできませんね(newのオーバーロードで置き換えはできますが、私には、 演算子のオーバーロード自体相当に腰が引けます。boostのように、汎用的で 一般的に知られたライブラリを使うのなら、だいぶ軽減されると思いますけど)。 ところで、DiksamをC++で書き直し、fix_tree.cppでたくさんnewが起きるということは、 DiksamでのExpressionやStatementの構造体をクラスにしておられるのだと思いますが、 これはやっぱり、fix_tree.cppではfix()、generate.cppではgenerate()という メンバ関数を作って、クラスごとにポリモルフィズムで呼び出しているのでしょうか? オブジェクト指向の教科書にはそう書いてありますが、実際にやってみると クラスごとに細かい制御ができなかったりモデルにロジックが侵食したりして あまりうまくいかない、と経験上思っておりますので。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1253] 状況(日記?)
投稿者:
2009/05/07 19:00:06

 fix_treeのところで多少手間取っていますが一応終了。トータルの結合 試験で多分たくさんのがバグが・・・  少し長いプログラムを読み込ませるだけで、細かいサイズのメモリーを 7千ぐらい、newとdeleteしているのを見るにつけ、これは結構システムに 負担ではないと思いつつ、区切りが出来たらboostの高速メモリー管理poolに 変えようとかと考えています。一括削除が可能だし。また、メモリー上のトラ ブルが起こったら追うだけでも大変だと思う、今のところそのトラブルには 遭遇していないのが救いです。バグは当たり前のようにありますが・・・  ちなみに、test.dkmで最高6800ぐらいnewします。  特に新しいところがなく日記的なので、不要だったら削除してください。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1252] Re:関数実装について
投稿者:
2009/05/04 22:30:19

>Diksam ver.0.4以降だと、ファイルをrequireしておけば、 >呼ぶ際は普通の関数呼び出しですけれど、 そうなんですか、同じものを再発明しそうですね。 >Emacs Lispはダイナミックロードですが、私としては初回呼び出しのタイムラグは >気にならないと思っているので、まあ問題ないと思っているのですけれども。 私の場合、スレッドが必要だと思うほどクリティカルな部分を意識しているので やはり、利用者がコンパイラ起動を意識したほうがいいかなと思っています。 >ということはDVMはひとつでグローバル変数とヒープ領域は共有ですね。 >結構ロックが大変そうな気はします。  この辺はまだ希望的観測の部分が多いので、実際に作りこんでみないと なんともいえない感じです。  今現在はfix_tree部分を作っていますが、途中でnew、deleteが頻発するので 思わず。new、deleteに被せて、newのアドレスとサイズをコンテナMAPに総て入れ、 deleteで検証する監視プログラムやサポ-トプログラムばかり作ってて脱線気味 です。目的プログラム70%残り30%は監視やデバックプログラムです・・・ 文字列リテラルも、wchar_tを使ってもポータビリティーが上がらないのでstring に変えてしまったし、diksam言語部分だけでも一通り動くようになるのはまだまだ 先です。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1251] Re:関数実装について
投稿者:(ぱ)こと管理人
2009/05/04 19:33:38

> 言語仕様から見ると、Aプログラムの内部からBファイル内にある関数B1を普通に >コールすることです。当初は、ファイル名.関数名();で起動しようか、関数プロ >タイプ宣言で"ファイル名":関数名();で内部的には普通の関数記述と思いましたが。 Diksam ver.0.4以降だと、ファイルをrequireしておけば、 呼ぶ際は普通の関数呼び出しですけれど、 >いつ重いコンパイラが走るかコントロール出来ないので、 .dkhにシグニチャ宣言だけ書いて.dkmに実装を書くと、関数呼び出し時にコンパイラが 動きますから、状況によって問題になるかもしれません(実装まで.dkhに書いてしまえば いいわけですけど)。 Emacs Lispはダイナミックロードですが、私としては初回呼び出しのタイムラグは 気にならないと思っているので、まあ問題ないと思っているのですけれども。 >スレッド起動の仕様 >普通に関数名(P1,,,Pn);を書くと戻ってくるまでコール元は待ちます。 >start(関数名,起動P,,,Pn);と書くとスレッド起動となります。 ということはDVMはひとつでグローバル変数とヒープ領域は共有ですね。 結構ロックが大変そうな気はします。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1250] 関数実装について
投稿者:
2009/05/02 18:30:12

>これは、CからDiksamの関数を関数名を指定して呼び出すということですよね。 内部的に見るとそうです。  言語仕様から見ると、Aプログラムの内部からBファイル内にある関数B1を普通に コールすることです。当初は、ファイル名.関数名();で起動しようか、関数プロ タイプ宣言で"ファイル名":関数名();で内部的には普通の関数記述と思いましたが。 いつ重いコンパイラが走るかコントロール出来ないので、プログラムファイル読込 み関数と破棄関数(中間コードリソースの破棄)を作ることにしました。  この仕様でVMの変更が発生します。それは、1ファイル内の関数コールはコンパ イラで関数アドレスを生成しますが。ファイル外の場合、関数アドレスではなく関 数名を持って、実行時リンクして関数コールする仕様が追加になります。 (最外枠ブロックの実行構文はなくなり、ファイル名起動ではmain()が実行) 中間コードの構造は。 親 ファイル1  ファイル親ー>子    ファイルn ↓   |----------¬    |----------¬ 子   関数1 ・・・・・・ 関数n  関数1 ・・・・・・ 関数n  の様に、階層構造の親子関係で関数置きに分離した中間コードになる予定です。 この、ファイルnの部分が必要時にコンパイルされ中間コードに追加される感じです。  この構造はちょうど関数単位のマルチスレッドに適応できます。 スレッド起動の仕様 普通に関数名(P1,,,Pn);を書くと戻ってくるまでコール元は待ちます。 start(関数名,起動P,,,Pn);と書くとスレッド起動となります。 例   thread_ID1 = start(fnc1,,,);   thread_ID2 = start(fnc1,,,);   thread_ID3 = start(fnc1,,,); と書くとメインスレッドと3つのfnc1スレッドが同時に動きます。 関数については、この様な仕様を組込みたいと考えています。 また、グローバルシステム変数とスレッド起動された関数は一般的なCのグローバ ル変数やスレッドとは、かなり性格が違ったものになります。でも、この点は実物 のめどが出来そうなときにでも、評価していただければ嬉しいと思っています。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1249] Re:その後の状況
投稿者:(ぱ)こと管理人
2009/05/02 03:39:28

訂正します。 >と思って見ていたらbaseが初期化されていない >ことに気付きました。またバグです。すみません (_o_) いくらなんでもこれじゃ動かないよな、と思ってよく考えると baseはローカル変数の参照に使うので関数内でしか使用されず、 関数を読んだ際にセットされるので問題ありませんでした。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1248] Re:その後の状況
投稿者:(ぱ)こと管理人
2009/05/02 03:14:14

>追加したい機能 >・関数指定起動、スクリプトファイル名と関数名を指定して起動 > (スクリプトファイル間の連携したプログラミングのために) これは、CからDiksamの関数を関数名を指定して呼び出すということですよね。 特定の関数を実行するには、dvm/execute.cのexecute()関数を、 http://kmaebashi.com/programmer/devlang/diksam_src_0_2/S/18.html#544 ・事前にdvmのcurrent_executableとcurrent_functionとpcを設定して  (プログラムカウンタは関数ごとなのでpcは0に設定)、 ・execute()関数を、適切な引数で呼び出す ことで可能なはずです。 ただ、実際にはDiksamからネイティブ関数を呼び出して そのネイティブ関数からさらにDiksamの関数を呼び出す、というケースも あるので、スタックポインタを設定の上、execute()関数のローカル変数 baseも引数で渡してやらないと… と思って見ていたらbaseが初期化されていない ことに気付きました。またバグです。すみません (_o_) gccの-Wallでは当てにならないですし、山さんがされたようにVisual Studioでも コンパイルしたいのですがなかなか時間が取れない状態です。明日からは連休ですが、 連休は連休でまた色々と… 編集さんはゲラを発送されたとのことですし(ん?) >その結果、diksam0.2.0の系譜をもつ別の言語になってしまいます。 >なので、言語名は別のものになります。そこでお聞きしたいので >す。diksam0.2.0の系譜をもつ別のものを作ることになりましたが、 >ここでお話しすることは可能でしょうか? まったく問題ありません。 > ぶちゃけて言います。気分を害したりしませんか?>< それはないです(^^) Diksamベースで新しい言語ができるのであれば、 どこをどう直されるのか興味深いです。
[この投稿を含むスレッドを表示] [この投稿を削除]