K.Maebashi's BBS

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

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

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

[367] サポートセンター
投稿者:774RR
2007/02/20 02:13:25

掲示板を読んでいたらなんとなく「さぽせん」ホームページを思い出しました。 ... っていやそれだけ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[366] お邪魔しますー
投稿者:hairo
2007/02/20 02:13:25

はじめまして。 ここ数日サイトに訪れさせてもらっています。 最近(ここ2、3年)ですがSQL+PHPで仕事することが多く、それまで無知だった自分がいつのまにやら基本構文(?)を覚えてしまい、無料サーバーを借りてDB組み込みつつ動的なものを作り始めました。 さしあたって、簡単な雑記帳やカウンターなどは楽にできました(それでも丸三日はかかりました)が、BBSはどうしたもんかなーとgoogleで回っていたら。このサイトに来ました。 ソースの半分くらいしか理解できてませんが、読んだ感じだとDBフィールド用意して、あのソースを貼り付けるだけで出来そうなんですが(笑) 使用してもよいでしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[365] Re:リバーシゲームのはさみ将棋への改造
投稿者:(ぱ)
2007/02/20 02:13:25

>http://revolver.at.infoseek.co.jp/hasami-vc.lzh  このリンクから.lzhファイルをダウンロードすることはできました。サイズは301バイト。  解凍してみたら、ショートカットのファイルがひとつだけあらわれました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[364] Re:リバーシゲームのはさみ将棋への改造
投稿者:SFファン
2007/02/20 02:13:25

当方がWebについて良く知らないため、ダウンロードして貰えなくてすみません。 今回もうまくいかないかも知れませんが、とりあえず貼って見ます。 http://revolver.at.infoseek.co.jp/hasami-vc.lzh
[この投稿を含むスレッドを表示] [この投稿を削除]
[363] Re:crowbar MEMモジュール
投稿者:tos
2007/02/20 02:13:25

> それだとおっしゃるとおりチェック漏れを起こすと思います。どういうわけか、 また、ボケた質問しているんじゃないかと思って、ドキドキしてましたが、 今回はあってたみたいで安心しました。 >というわけで、私はこの通りポカもミスも人並み以上にしますので、 >全然たいしたことはないです f(^^;;; いえいえ、これからも前橋さんのソースで勉強させていただきます。 ありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[362] Re:「プログラミング言語を作る」
投稿者:(ぱ)
2007/02/20 02:13:25

>実装を始めて気がついたのですが、goto文って実はもっとも単純だと >思っていたのですが、実は難しいのですね。  です。crowbarにgotoがないのはそのためです(w。かろうじてbreakとcontinueは ありますが、これも戻り値でちまちま返すことになってしまっています。 # Rubyはこのへんをsetjmpとlongjmpでやっているようですが。 >というように、状況に応じて改行を文の区切り文字と認識したりあるいは >無視したりしています。Ruby では Lex などの字句解析機を使わずに自前の >実装を使われているそうなので、ありものの字句解析機を利用しなかったのは、 >利用できなかったからなのでは?と勝手に想像しています。  いきなり答をばらす行為になるのかもしれませんが、Rubyの実装については、 以下のページに詳細な説明があります。 http://i.loveruby.net/ja/rhg/index.html  「状態付きスキャナ」にも、1章が割り当てられています。
[この投稿を含むスレッドを表示] [この投稿を削除]
[361] Re:リバーシゲームのはさみ将棋への改造
投稿者:(ぱ)
2007/02/20 02:13:25

>はじめまして。  どうもです。  ここを見ている第三者のために経緯を説明すると、SFファンさんは 既にJavaWorld誌経由で質問されていて、私からも一度回答を返しています。 ただあまり編集さんを煩わせるのもなんですし、よろしければ掲示板の方へ、 と私が書いたので、こちらで質問されたようです。 >そこでVC++への移植を試みました。しかし時々盤オブジェクトの参照で >アクセスバイオレーションが起きてしまいます。 >Java版と同じ様に盤(cell)をnewしていますが、別クラスもしくは >Boardクラスの他のメソッドから見れていない様です。 >この件についてJavaWorld経由で前橋氏から解答を貰いましたが >盤オブジェクトは構造体にしなければいけない様な事が書いてありました。  そういうことを書いた覚えはないですが…  私が書いたのは、以下の通りです。 # その他、本当にC++にすれば速くなるかは疑問、という趣旨のことも書きましたが。 >可能性としては、以下のようなことが考えられるでしょうか。 > >・メンバにアクセス修飾子を付けない場合のデフォルトの意味が、JavaとC++では > 異なる(Javaはデフォルトでパッケージ内丸見えだがC++はデフォルトでprivate)。 >・高速化を狙ったのなら、1手先読みするたびにBoardを毎回newするのではなく、 > Boardをスタック上に確保するような変更を加えたのでしょうか? > もしそうだとして、盤面の配列部分をJava版と同じようにヒープに確保して > いるとすれば、コピーコンストラクタを正しく書かないと動作しません。 > # Boardをスタックに置いておきながら、盤面の配列をヒープに取るようなことは > # 普通しないと思うので、この可能性は薄そうですが。  ひとまず「アクセスバイオレーション」とのことなので、コンパイル時のエラー ではなく実行時のエラーなのでしょう。よってひとつめの可能性は排除できます。  「Java版と同じ様に盤(cell)をnewしていますが」とありますが、もしこれが、 「Boardはスタックにとっているのに2次元配列cellはヒープにとっている」という ことなら、ふたつめの可能性は考慮する価値があるかもしれませんが… 私のソースを直接C++で書き直したのなら、Boardこそヒープに取るでしょうし、 やっぱり可能性は薄いように思います。 >http://revolver.at.infoseek.co.jp/hasami-vc  403 Forbiddenです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[360] Re:crowbar MEMモジュール
投稿者:(ぱ)
2007/02/20 02:13:25

> とはならず、「(char*)&header[1] - (char*)header->s.mark)とMARK_SIZEの隙間」 >の方が先に壊れるような気がするのですが、違いますでしょうか?  すみません、勘違いしていました。tosさんが心配しておられるのは、 アプリケーションに返す領域の「前の」MARK部分なのですね。  それだとおっしゃるとおりチェック漏れを起こすと思います。どういうわけか、 後ろのMARKのことだとばかり思い込んでいました。  ご指摘ありがとうございました。次のバージョンで直します。 >ただ、私は前橋さんを勝手に師匠と思って、ソースを勉強させていただいて >いますので、もう少しお付き合いください。 というわけで、私はこの通りポカもミスも人並み以上にしますので、 全然たいしたことはないです f(^^;;;
[この投稿を含むスレッドを表示] [この投稿を削除]
[359] Re:「プログラミング言語を作る」
投稿者:緒方
2007/02/20 02:13:25

>>>・制御構文はとりあえずifとgotoのみ(とほほ・・・) >>>・他の制御構文はifとgotoで実装してライブラリ提供 >> >> どのような形式で実行する言語を想定しておられますでしょうか。 > >むむっ、実はあまり考えていません。あれこれ空想する際には、アセンブリのイメージで考えていて、無条件ジャンプと条件ジャンプがあればとりあえず事足りるかな、という風に思って上記のように書きました。 実装を始めて気がついたのですが、goto文って実はもっとも単純だと思っていたのですが、実は難しいのですね。 今はソースを読み込んだら即構文木を作って評価するインタープリタを作っているのですが、今のインタープリタにgoto文を実装するとすると、上方向にジャンプする場合も下方向にジャンプする場合も、入力ストリームをラベル位置まで巻き戻したりスキップしたりしなければなりません。BASICのgoto文ってどういう実装になっているか調べてみようかと思っています。 >>>b, a = a, b #スワップ 他にも難しい実装に気がつきました。Ruby のように文の区切り文字を省略させたいのですが、これがまたかなり難しいです。Ruby だと 1 + 2 # 1+2 と評価される 1 # 1 と評価される + 2 # +2 と評価される 1 # 1 と評価される + # この時点では式が継続するものと予測されるので評価しない 2 # 上の行と合わせて +2 と評価される 1 + # そういえばこのケースは試してないですが、 2 # 多分 1+2 と評価されるのでは? というように、状況に応じて改行を文の区切り文字と認識したりあるいは無視したりしています。Ruby では Lex などの字句解析機を使わずに自前の実装を使われているそうなので、ありものの字句解析機を利用しなかったのは、利用できなかったからなのでは?と勝手に想像しています。 というのも、上記のような改行仕様を flex で実装しようとしたところ、状態遷移だけでかなり複雑になってしまい、私ではお手上げでした。
[この投稿を含むスレッドを表示] [この投稿を削除]
[358] リバーシゲームのはさみ将棋への改造
投稿者:SFファン
2007/02/20 02:13:25

はじめまして。 「JavaWorld」2003年3月号掲載の前橋氏作のリバーシゲームをはさみ将棋に改造しました。 しかし3手読みが限界で強くありません。 そこでVC++への移植を試みました。しかし時々盤オブジェクトの参照でアクセスバイオレーションが起きてしまいます。 Java版と同じ様に盤(cell)をnewしていますが、別クラスもしくはBoardクラスの他のメソッドから見れていない様です。 この件についてJavaWorld経由で前橋氏から解答を貰いましたが盤オブジェクトは構造体にしなければいけない様な事が書いてありました。 以前作りかけていたはさみ将棋に前橋氏作のリバーシゲームを改造したものを上乗せしたので、まだ構造的におかしいですが、問題点があればご指摘をお願いします。 http://revolver.at.infoseek.co.jp/hasami-vc
[この投稿を含むスレッドを表示] [この投稿を削除]
[357] Re:crowbar MEMモジュール
投稿者:tos
2007/02/20 02:13:25

細かい突っ込みで時間を取っていただき、申し訳ありません。 ただ、私は前橋さんを勝手に師匠と思って、ソースを勉強させていただいて いますので、もう少しお付き合いください。 (char*)&header[1] - (char*)header->s.markがパディングを考慮したものだとすると、 (char*)&header[1] - (char*)header->s.markの値は、MARK_SIZEよりも大きい場合が あると思います。 そうすると、 >しかし、このへんが壊れるのはほとんど配列のオーバランで、もしそうなら、 >(char*)&header[1] - (char*)header->s.mark)とMARK_SIZEの隙間より先に、 >MARK_SIZEでチェックしている部分が壊れるはずです。 とはならず、「(char*)&header[1] - (char*)header->s.mark)とMARK_SIZEの隙間」 の方が先に壊れるような気がするのですが、違いますでしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[356] Re:crowbar MEMモジュール
投稿者:(ぱ)
2007/02/20 02:13:25

>check_mark_sub(unsigned char *mark) ... >でチェックしているのは、MARK_SIZEのようです。 はい。これは単に、アプリケーションに返す領域の「前に入れたマーク」と 「後ろに入れたマーク」で同じcheck_mark_sub()を使いたかったため …だったと思います。要するに単なる手抜きです。 関連するソースはこのへん: http://kmaebashi.com/programmer/devlang/crowbar_src_0_1_01/S/5.html#148 >これだと、(char*)&header[1] - (char*)header->s.mark)がMARK_SIZEでは無かった場合、 >チェック漏れが起きてしまいそうな気がするのですが、あっていますでしょうか?(ヨワヨワです) (char*)&header[1] - (char*)header->s.mark)とMARK_SIZEの差にあたる部分を 選択的に破壊するようなバグがあれば、確かにチェック漏れを起こすはずです。 しかし、このへんが壊れるのはほとんど配列のオーバランで、もしそうなら、 (char*)&header[1] - (char*)header->s.mark)とMARK_SIZEの隙間より先に、 MARK_SIZEでチェックしている部分が壊れるはずです。 MEMでできるのはどっちみち確率的なチェックでしかありません。たとえば たまたま0xCDでマーク部分を破壊されたら気付きませんし、MEMで保持している 連結リストをぶっ壊されたら原因の究明は困難になってしまいます。 そう考えれば、この程度のチェックの甘さは許容範囲かなあ、と思っています。 だったら0xCDを詰めるのも、最初からMARKのサイズだけでいいじゃん、という ツッコミはもちろんあり得るわけですが、そんなことでたいして速度が稼げる わけじゃなし、どうでもいいんじゃないかなあ、と。 ただし、もちろんmark_check_head()とmark_check_tail()を別々に 作ってもたいした手間ではありません。チェックの甘さはさておき、 ソースの統一感という点からすると、修正したほうがよいかもしれませんね。 正直、あまり優先度は高くないですが、気が向いたら直しておきます。
[この投稿を含むスレッドを表示] [この投稿を削除]
[355] crowbar MEMモジュール
投稿者:tos
2007/02/20 02:13:25

皆さんこんにちは、tosです。 crowbarのMEMモジュールに関して質問があります。 memory.cの void set_header(Header *header, int size, char *filename, int line) { . . . memset(header->s.mark, MARK, (char*)&header[1] - (char*)header->s.mark); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } でmemsetのサイズとしてMARK_SIZEでは無く、上記のようなサイズを設定しているのは、 パディングを考慮してのことなのかなと思いますが、 void check_mark_sub(unsigned char *mark) { int i; for (i = 0; i < MARK_SIZE; i++) { if (mark[i] != MARK) { fprintf(stderr, "bad mark\n"); abort(); } } } でチェックしているのは、MARK_SIZEのようです。 これだと、(char*)&header[1] - (char*)header->s.mark)がMARK_SIZEでは無かった場合、 チェック漏れが起きてしまいそうな気がするのですが、あっていますでしょうか?(ヨワヨワです)
[この投稿を含むスレッドを表示] [この投稿を削除]
[354] Re:プログラミング言語を作る
投稿者:mizu
2007/02/20 02:13:25

>クロージャがネストするたびに、配列の要素が増えるのではなく、配列が >増えるわけですよね。つまり2次元配列(配列の配列)が渡ることになる、と。 >あるいは、ネストが増えるたびに引数の数そのものが増えるのかも >しれませんね。 引数の数が増える方を想定していました。2次元配列の方だと、クロージャから 外側の環境の変数にアクセスするたびに2次元配列にアクセスすることになる分、 性能が低下しそうなので。 > >どちらにせよ、それなら納得です。 > >最近本格的に時間がなくて、断片的な疑問の提示しかできなかったため >余計なお手間を取らせてしまいました。すみません。 いえ、こちらこそ、説明が足りなかったせいで余計な手間を取らせてすいません でした。
[この投稿を含むスレッドを表示] [この投稿を削除]
[353] Re:「プログラミング言語を作る」
投稿者:(ぱ)
2007/02/20 02:13:25

>foreach と using を分けた C# もそれはそれで偉い、というか >何でもクロージャよりそっちのほうが個人的にはまっとうな >考え方という気が現在はしていますけどね。 私も基本的にはそう思うんですが、時々思うのは、 「言語仕様がライブラリに依存しているのはなんかヘン」ってことです。 foreachはIEnumerableに依存していますよね。 まあでもそれを言えばピュアなOO言語は数値などのリテラルもクラスの インスタンスですし、Cだってexit()に依存しているとは言えるので、 気にするほうがおかしいのかもしれません。 crowbarも、配列の生成は、配列リテラルを除きネイティブ関数に頼るつもりですし。
[この投稿を含むスレッドを表示] [この投稿を削除]
[352] Re:プログラミング言語を作る
投稿者:(ぱ)
2007/02/20 02:13:25

>すいません。説明不足でした。前の例で配列を1つしかクロージャに渡して >いないのは、あの例ではクロージャがネストしていないため、そうなっている >だけで、クロージャのネストが増えるごとに、クロージャに渡される配列の数 >は1つずつ増えて行く仕組みになっています。つまり、クロージャがn段ネスト >した場合、n個の配列がクロージャに渡されることになります。 クロージャがネストするたびに、配列の要素が増えるのではなく、配列が 増えるわけですよね。つまり2次元配列(配列の配列)が渡ることになる、と。 あるいは、ネストが増えるたびに引数の数そのものが増えるのかも しれませんね。 どちらにせよ、それなら納得です。 最近本格的に時間がなくて、断片的な疑問の提示しかできなかったため 余計なお手間を取らせてしまいました。すみません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[351] Re:プログラミング言語を作る
投稿者:mizu
2007/02/20 02:13:25

>まず前提として、 > >・クロージャはそれ自体が式なので、クロージャの中にも書けるはず。 > よって、クロージャはネスト可能。 >・ということは、内側のクロージャは、外側のクロージャの環境と、 > さらにその外側(普通の関数)の両方の環境が見えなければならない。 > >というのがあって、mizuさんの案だと配列をひとつしか渡していないので、 >いいのかな、と思ったわけです。 すいません。説明不足でした。前の例で配列を1つしかクロージャに渡して いないのは、あの例ではクロージャがネストしていないため、そうなっている だけで、クロージャのネストが増えるごとに、クロージャに渡される配列の数 は1つずつ増えて行く仕組みになっています。つまり、クロージャがn段ネスト した場合、n個の配列がクロージャに渡されることになります。 > 再帰がなければ静的にインデックス計算することも可能でしょうが、 >再帰を許すと、インデックスが動的に変化することになりませんか、 >というのが先の投稿の意図です。 ># 私はクロージャ初心者なので何か勘違いしている可能性はありますが… クロージャのネスト段数は静的に決定され、かつ、クロージャから 参照されている変数がどのクロージャ(関数)のものであるかは、静的に決定 可能なので、再帰の有無に関わらず、(クロージャから参照される)変数の インデックスは静的に計算できるはずだと思うのですが…。何か勘違いしている のかもしれませんので、もう少し考えてみます。
[この投稿を含むスレッドを表示] [この投稿を削除]
[350] Re:「プログラミング言語を作る」
投稿者:Shin
2007/02/20 02:13:25

>> foreach(collection, function(item) { >> print(item); >> }); >> >>こんな感じだと読みにくいですかねえ。 > >そんなことはないですよ。むしろ読みやすいと思います。 Ruby なら collection.foreach { |item| print item } なわけで、メソッド/クロージャによるライブラリ的実装の ほうがよっぽど読みやすいとは言えそうですねぇ。 # 他のに多様な仕組みとの共通性という意味で これはクロージャの構文の勝利ですね。 foreach と using を分けた C# もそれはそれで偉い、というか 何でもクロージャよりそっちのほうが個人的にはまっとうな 考え方という気が現在はしていますけどね。 # Net::HTTP.start(host) { |http| ... } みたいに # 後始末のためにクロージャを使うのってなんか変な感じがしている
[この投稿を含むスレッドを表示] [この投稿を削除]
[349] Re:プログラミング言語を作る
投稿者:(ぱ)
2007/02/20 02:13:25

>> ええと、クロージャが再帰した時はどうなるのでしょうか。Pascalの >>スタティックリンクのような仕掛けがないと困るような気が… >>すみませんよぱらいなので頭動いてないです。 まず前提として、 ・クロージャはそれ自体が式なので、クロージャの中にも書けるはず。  よって、クロージャはネスト可能。 ・ということは、内側のクロージャは、外側のクロージャの環境と、  さらにその外側(普通の関数)の両方の環境が見えなければならない。 というのがあって、mizuさんの案だと配列をひとつしか渡していないので、 いいのかな、と思ったわけです。  再帰がなければ静的にインデックス計算することも可能でしょうが、 再帰を許すと、インデックスが動的に変化することになりませんか、 というのが先の投稿の意図です。 # 私はクロージャ初心者なので何か勘違いしている可能性はありますが… >あと、Pascalはよく知らないのですが、Pascalのスタティックリンクとは >どのようなものなのでしょうか?  Pascalは関数のネストができるので、内側の関数からは外側の関数の ローカル変数が参照できます。かつ再帰を許すため、現状のスタックの トップからの、外側の関数のローカル変数の位置は静的には決まりません。 そこで、最新の環境に、外周の関数の環境へのポインタを保持していて それをスタティックリンクと呼びます。 # Pascalの処理系を読んだわけではないので、「エキスパートCプログラミング」の # 受け売りですが。 >とすると、変数のルックアップは、ある環境を探索して、見つからなければ >外側の環境へのリンクをたどって…という風に行われるのでしょうか。 そのつもりです。JavaScriptではこんな感じらしいですし。 http://www.hawk.34sp.com/stdpls/jsnotes/jssinso/  ただ、グローバル変数を単なる再外周の環境として扱うか、特別扱いするかは 現在悩んでいるところです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[348] Re:プログラミング言語を作る
投稿者:mizu
2007/02/20 02:13:25

> うーん、私はLispはEmacs Lispやxyzzy Lispで遊んだ程度ですので、 >Lispそのものについては何も言いませんが(Paul Grahamのエッセイは日本語訳された >範囲ではたぶん全部読んでますし、Lispを悪く言うつもりはないですが)、 私も、Lispは、Schemeとかで遊んだ程度なので、あまり偉そうには言えないです。 >コンパイラコンパイラが使える環境なら、多少の構文の複雑さは問題にならない >はずです。 確かにそうだと思います。しかし、構文を少しずつ拡張していくという作業は、 いかにパーザジェネレータを使っていても、面倒ではあります。その点、Lisp系なら 一度S式パーサを書いておけば、基本的にはパーザをいじらなくても構文を拡張 できる(まあ、S式で書けるものしか基本的には書けませんが)というのは、嬉しい気が します。それが初心者にとって、どれだけ嬉しいかはわかりませんが。 >だとすれば、初心者さんにとって、馴染みの薄いLispの勉強と、 >言語処理系の作成というふたつのことを同時に勉強させるのは酷というものでは >ないでしょうか。 Lispの核となる概念自体はかなりシンプル(だと思う)なので、覚えるべき事柄は そう多く無い気もします。もちろん、Common LispなりSchemeなりを実装しようと 思うと、勉強しなければならないことがたくさんあるはずですが、処理系作成の 勉強としては、「Lispのようなもの」を作れれば十分ですし。ただ、馴染みが 薄いため、取っ付きが悪いというのはありそうです。 > もっとも、何かを理解しようと思ったら、それを作ってみるのが一番手っ取り早い >とは思っていまして、Lispを勉強したい人に「じゃあLispを作ってみようよ」という >提案は有効だと思います。でも、言語処理系を作ってみたい、という人が、 >本当に作りたいのは、Lispなんでしょうか。 たぶん(多くの人にとっては)違うと思います。しかし、とりあえず練習として 作ってみることで、言語処理系の作成に必要な基礎知識が身につくという効果は あると思います。どうせ、初めて作る言語で、いきなり自分の欲しい言語を作る なんてのは無理ですし。 >>基本的なアイデアとしては、いわゆる「単純委譲」をコンパイラが自動生成する > > 了解です。 > ところで、この形式で、MyListはArrayListなんでしょうか。 > そうだとすれば、多重継承を許そうとすると、「ArrayListインタフェース」のような >インタフェースをたくさん作らなければならないような気がします。 いえ。あくまで委譲コードの自動生成なので、型としては、ArrayListと MyListは何ら関係がありません。ですから、型の継承関係を作りたけ れば、別途クラスを継承するか、インタフェースを実装します。 例えば、MouseListenerとWindowListenerのインタフェースを多重継承して、 それぞれの実装をMouseAdapterとWindowAdapterに委譲するコードは、 class MouseAndWindowAdapter implements MouseListener, WindowListener { /*MouseListenerインタフェースに対する呼び出しを委譲*/ forward MouseListener mouseListener_ = new MouseAdapter(); /*WindowListenerインタフェースに対する呼び出しを委譲*/ forward WindowListener windowListener_ = new WindowAdapter(); } と書けます。 >>で、問題になっている環境へのアクセス方法ですが、クロージャから外側の >>環境にアクセスしていることをコンパイラが検出したら、外側の環境での変数 >>へのアクセスをObject型配列の要素に対するアクセスに変換して、Object型配列 >>への参照を、クロージャに渡すという方法を取ります。 > > ええと、クロージャが再帰した時はどうなるのでしょうか。Pascalの >スタティックリンクのような仕掛けがないと困るような気が… >すみませんよぱらいなので頭動いてないです。 クロージャの中で、自分を再帰的に呼び出したときということでしょうか。 それなら、おそらく問題無いと思います。 例えば、以下のような再帰でフィボナッチ数列を計算するクロージャfibが あったとして(これだと、クロージャにする意味があまりありませんが)、 interface UnaryIntegerFunction { int call(int arg); } class Hoge{ public static void main(String[] args){ UnaryIntegerFunction fib = #(int n){ if(n == 1 || n == 2){ return 1; }else{ return fib.call(n - 1) + fib.call(n - 2); } }; System.out.println(fib.call(3)); } } これは、 class UnaryIntegerFunction$1 implements UnaryIntegerFunction { private Object[] environment_; UnaryIntegerFunction(Object[] environment){ environment_ = environment; } public int call(int n){ if(n < 2){ return 1; }else{ return ((UnaryIntegerFunction)environment_[1]).call(n - 1) + ((UnaryIntegerFunction)environment_[1]).call(n - 2); } } } class Hoge { public static void main(String[] args){ Object[] environment = new Object[2]; environment[0] = args; environment[1] = new UnaryIntegerFunction$1(environment); System.out.println("fib(3) = " + ((UnaryIntegerFunction)environment[1]).call(3)); } } というコードに変換されます(先の投稿の例では、引数をenvironment 配列に入れるのを忘れていたので、若干先の例とは変換のされ方が違っています)。 このコードは問題無く動くと思うのですが、何か勘違いしているでしょうか? あと、Pascalはよく知らないのですが、Pascalのスタティックリンクとは どのようなものなのでしょうか? > ちなみにですが、crowbarはJavaScript的に環境ごとに連想配列を持ち、 > 外側環境へのリンクを持とうと思っています。 とすると、変数のルックアップは、ある環境を探索して、見つからなければ 外側の環境へのリンクをたどって…という風に行われるのでしょうか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[347] Re:プログラミング言語を作る
投稿者:(ぱ)
2007/02/20 02:13:25

>簡単に実装するなら、Lisp系言語などが楽でいいのではと思いましたが、 >どうでしょうか。普通の言語に比べて、構文がちょっと特殊ですが、機能 >拡張がわりと容易ですし、言語設計の面白さは十分に味わうことができるの >ではないかと思います。  うーん、私はLispはEmacs Lispやxyzzy Lispで遊んだ程度ですので、 Lispそのものについては何も言いませんが(Paul Grahamのエッセイは日本語訳された 範囲ではたぶん全部読んでますし、Lispを悪く言うつもりはないですが)、 いわゆる「普通のプログラマ」に馴染みが薄いというのは確かだと思うわけです。  んで、この辺のスレ http://pc8.2ch.net/test/read.cgi/tech/1106129164/ とか見るにつけ、「Lispなら処理系作るの簡単だよ」というアドバイスがちょくちょく あって、それはそれで嘘ではないと思うのですが、yaccなりJavaCCなりの コンパイラコンパイラが使える環境なら、多少の構文の複雑さは問題にならない はずです。だとすれば、初心者さんにとって、馴染みの薄いLispの勉強と、 言語処理系の作成というふたつのことを同時に勉強させるのは酷というものでは ないでしょうか。  もっとも、何かを理解しようと思ったら、それを作ってみるのが一番手っ取り早い とは思っていまして、Lispを勉強したい人に「じゃあLispを作ってみようよ」という 提案は有効だと思います。でも、言語処理系を作ってみたい、という人が、 本当に作りたいのは、Lispなんでしょうか。 >基本的なアイデアとしては、いわゆる「単純委譲」をコンパイラが自動生成する  了解です。  ところで、この形式で、MyListはArrayListなんでしょうか。  そうだとすれば、多重継承を許そうとすると、「ArrayListインタフェース」のような インタフェースをたくさん作らなければならないような気がします。 >で、問題になっている環境へのアクセス方法ですが、クロージャから外側の >環境にアクセスしていることをコンパイラが検出したら、外側の環境での変数 >へのアクセスをObject型配列の要素に対するアクセスに変換して、Object型配列 >への参照を、クロージャに渡すという方法を取ります。  ええと、クロージャが再帰した時はどうなるのでしょうか。Pascalの スタティックリンクのような仕掛けがないと困るような気が… すみませんよぱらいなので頭動いてないです。  ちなみにですが、crowbarはJavaScript的に環境ごとに連想配列を持ち、 外側環境へのリンクを持とうと思っています。
[この投稿を含むスレッドを表示] [この投稿を削除]
[346] Re:プログラミング言語を作る
投稿者:mizu
2007/02/20 02:13:25

今回の投稿は、説明の都合上、大分長くなってしまいました。迷惑でしたら、 すいません。 >やってみるとそんなに難しくはないんですよね。実際、今回の企画はそれを >示そうと思ってはじめました。時間がなくてなかなか思うに任せていませんが。 ># そんなに難しくはない、ということを示したいんだから、あっという間に ># 実装できた方が説得力あるんでしょうけどねえ。 簡単に実装するなら、Lisp系言語などが楽でいいのではと思いましたが、 どうでしょうか。普通の言語に比べて、構文がちょっと特殊ですが、機能 拡張がわりと容易ですし、言語設計の面白さは十分に味わうことができるの ではないかと思います。 >・委譲の言語仕様とか、 基本的なアイデアとしては、いわゆる「単純委譲」をコンパイラが自動生成する というもので、Java風に書くと、 class MyList{ forward List list_ = new ArrayList();//委譲宣言 } というコードから、 class MyList{ List list_ = new ArrayList(); public void add(Object o){ list_.add(o); public Object get(index i){ return list_.get(i); } } というコードをコンパイラが生成します。もちろん、これだけだと メソッド名が衝突したときに問題が発生しますが、経験から言って、 そのような衝突は、おそらくさほど頻度は高くないだろうと思われるので、 コンパイルエラーにして、衝突したメソッドのみ、プログラマにどのフィールドに 委譲するか(あるいはそもそも委譲せず、そのメソッドを新たに定義するか)を 選択させれば良いと考えています。 あと、全部のメソッドを委譲するだけでは不便なので、委譲したくないメソッドを 列挙する機能も必要かなと考えていますが、これはまだ実装するかどうかわかり ません。 >・クロージャの実装方法(環境へのアクセス方法)とか、 実は、クロージャの部分はまだ実装できていないのですが、仕様は大体決まって いて、クロージャは、新たなデータ型を導入するのではなく、インタフェース の実装クラスのインスタンスとして、クロージャを生成するという方法を 取ろうと思っています。 ActionListener n = #(ActionEvent event){ System.out.println("actionPerformed"); }; というコード(#以降がクロージャの定義で、eventはクロージャの仮引数です)は、 class ActionListener$1 implements ActionListener { public void actionPerformed(ActionEvent event){ System.out.println("actionPerformed"); } } ... ActionListener n = new ActionListener$1(); というコードにコンパイルされます。 ここでは、ActionListenerがメソッドを1つしか持っていないため、クロージャ の定義では、メソッド名を指定する必要はありませんが、メソッドを複数持った インタフェースの場合、対応するメソッドを指定する構文を用意しようかと 思っています。 で、問題になっている環境へのアクセス方法ですが、クロージャから外側の 環境にアクセスしていることをコンパイラが検出したら、外側の環境での変数 へのアクセスをObject型配列の要素に対するアクセスに変換して、Object型配列 への参照を、クロージャに渡すという方法を取ります。例えば、 class Hoge{ public static void main(String[] args){ int n = 0; ActionListener listener = #(ActionEvent event){ n++; }; listener.actionPerformed(null); System.out.println("n: " + n); } } というコードは、 class ActionListener$1 implements ActionListener { private Object[] environment_; ActionListener(Object[] environment){ environment_ = environment; } public void actionPerformed(ActionEvent event){ environment_[0] = new Integer(((Integer)environment_[0]).intValue() + 1); } } class Hoge{ public static void main(String[] args){ Object[] environment = new Object[1]; ActionListener listener = new ActionListener$1(environment); listener.actionPerformed(null); System.out.println("n: " + ((Integer)environment[0]).intValue()); } } というコードにコンパイルされます。このようなクロージャの実装方式は、 クロージャを新たなデータ型として導入するのに比べて、正直使い勝手は 悪いですが、既存のライブラリを活用するという点では、この方式の方が 良いのではないかと思っています。 >・型宣言を省略する方法とか(静的型とのことなので、レキシカルな最初の代入から推測?) その通りです。例えば、以下の代入があったとして、 n = 1; 代入があった時点でのスコープで、nが宣言されてされていなければ、それは int n = 1; という宣言とみなされます。代入される値の型が参照型の場合も、同じですが、 nullが代入される場合だけやや特殊で、 n = null; は、 Object n = null; とみなされます。この機能があれば、例えば、よくある String line; while((line = reader.readLine()) != null){ .. } というコードが、変数宣言無しで、 while((line = reader.readLine()) != null){ .. } だけで書けるようになります(lineのスコープはwhile文で閉じています)。 以上、長々と説明を書かせていただきましたが、よろしければツッコミや 意見をいただければ幸いです。 > 公開される日を楽しみにしています。 どうも有難うございます。頑張って開発を進めたいと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[345] Re:プログラミング言語を作る
投稿者:(ぱ)
2007/02/20 02:13:25

>プログラミング言語を作るというと、 >やはり「難しそう」というイメージがあるのか、敬遠されることが >多いです。 やってみるとそんなに難しくはないんですよね。実際、今回の企画はそれを 示そうと思ってはじめました。時間がなくてなかなか思うに任せていませんが。 # そんなに難しくはない、ということを示したいんだから、あっという間に # 実装できた方が説得力あるんでしょうけどねえ。 >実は私も新しいプログラミング言語をJavaCCで作っていまして、近いうちに >公開しようかと考えているところです。 おお、すばらしい。 >どんな言語かと言いますと、Java VMのバイトコードを吐く、静的型の >オブジェクト指向言語で、JavaのOOP機能に、委譲やクロージャなどを備えた言語 >です。既にほとんどの機能のコンパイルができる所まで完成していて、今少しずつ >ドキュメントを書いているところです。 > >一応、特色としては、Javaライクな静的型オブジェクト指向言語でありながら、 >スクリプト言語のようにトップレベルにスクリプトがかけたり、型宣言が省略可能 >な辺りでしょうか。 ・委譲の言語仕様とか、 ・クロージャの実装方法(環境へのアクセス方法)とか、 ・型宣言を省略する方法とか(静的型とのことなので、レキシカルな最初の代入から推測?)  等に興味があります。  公開される日を楽しみにしています。
[この投稿を含むスレッドを表示] [この投稿を削除]
[344] プログラミング言語を作る
投稿者:mizu
2007/02/20 02:13:25

こんにちは。 新企画「プログラミング言語を作る」楽しみにしています。私はよく 友達(もちろん、一応プログラミング経験者の)に、「言語作ろうぜ。 面白いよ」とよく言っているのですが、プログラミング言語を作るというと、 やはり「難しそう」というイメージがあるのか、敬遠されることが 多いです。 こういうページを見て、「俺言語を作ってやろう」という人が増えるなら、 プログラミング言語好きとしては、嬉しいので、頑張ってください。もちろん、 無理をされない程度に。 ------------------------ 以下、ちょっと宣伝です。 実は私も新しいプログラミング言語をJavaCCで作っていまして、近いうちに 公開しようかと考えているところです。 どんな言語かと言いますと、Java VMのバイトコードを吐く、静的型の オブジェクト指向言語で、JavaのOOP機能に、委譲やクロージャなどを備えた言語 です。既にほとんどの機能のコンパイルができる所まで完成していて、今少しずつ ドキュメントを書いているところです。 一応、特色としては、Javaライクな静的型オブジェクト指向言語でありながら、 スクリプト言語のようにトップレベルにスクリプトがかけたり、型宣言が省略可能 な辺りでしょうか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[343] Re:「プログラミング言語を作る」
投稿者:緒方
2007/02/20 02:13:25

>>・制御構文はとりあえずifとgotoのみ(とほほ・・・) >>・他の制御構文はifとgotoで実装してライブラリ提供 > > どのような形式で実行する言語を想定しておられますでしょうか。 むむっ、実はあまり考えていません。あれこれ空想する際には、アセンブリのイメージで考えていて、無条件ジャンプと条件ジャンプがあればとりあえず事足りるかな、という風に思って上記のように書きました。 中間コードを吐くタイプにしようかと考えていて、中間コードはXMLにしようかとも思っています。 > foreach(collection, function(item) { > print(item); > }); > >こんな感じだと読みにくいですかねえ。 そんなことはないですよ。むしろ読みやすいと思います。 >> return x + y, x * y #戻り値の数は任意個数 >>b, a = a, b #スワップ > >これはおそらくリストのような概念を導入し、コンマで区切った式でリストが >生成され、代入時左辺がリストで区切られていると、対応する要素に代入される、 >ということですよね。 >関数呼び出しの際も引数がコンマで区切られていますが、これも、リストとして >渡されて、仮引数に代入される、ということでしょうか。面白そうだと思います。 すごい考察です。僕はそこまで考えていませんでした(^-^;
[この投稿を含むスレッドを表示] [この投稿を削除]
[342] Re:「プログラミング言語を作る」
投稿者:(ぱ)
2007/02/20 02:13:25

>・制御構文はとりあえずifとgotoのみ(とほほ・・・) >・他の制御構文はifとgotoで実装してライブラリ提供  どのような形式で実行する言語を想定しておられますでしょうか。  gotoって、現状のcrowbarのような、解析木実行形式の言語だと、結構実装が 難しいと思っています。バイトコード実行形式だと楽なんですが。  制御構造をライブラリで提供する、というのは、crowbarでも考えてはいて、 クロージャで実現できると思ってはいますが…  foreach(collection, function(item) { print(item); }); こんな感じだと読みにくいですかねえ。 > return x + y, x * y #戻り値の数は任意個数 >b, a = a, b #スワップ これはおそらくリストのような概念を導入し、コンマで区切った式でリストが 生成され、代入時左辺がリストで区切られていると、対応する要素に代入される、 ということですよね。 関数呼び出しの際も引数がコンマで区切られていますが、これも、リストとして 渡されて、仮引数に代入される、ということでしょうか。面白そうだと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[341] Re:「プログラミング言語を作る」
投稿者:緒方
2007/02/20 02:13:25

>>Java並みとはいわないまでも、Digital Marsにはもうちょっとがんばって、 >>標準ライブラリをもう少し整えてもらいたいものです。 > > むむ。言語作りかけの身としてはプレッシャーです (^^; うっ、墓穴だったかも(^-^;; でも思うに、言語仕様はシンプルで、機能はライブラリとして実現するのがやっぱり移植性とかメンテナンスとかを考えるとベストなので、ライブラリ作りは必須ですよね。でも、それこそシェアを握っている言語のライブラリ相当をそろえるのは不可能なので、 >いっそWindowsに特化してゲームとかを楽に作れる言語にしようか、とか >考えているところです。 特定用途に特化したライブラリでテリトリーを構築するのはよい案ですね。かくいう僕はターゲットはまだ決めてないんですが、プロトタイプはこんな言語にしようと考えています。 ・いわゆる型なし ・制御構文はとりあえずifとgotoのみ(とほほ・・・) ・他の制御構文はifとgotoで実装してライブラリ提供 def foo(x, y) { #関数宣言 return x + y, x * y #戻り値の数は任意個数 } a, b = foo(10, 20) #セミコロン不要 b, a = a, b #スワップ print(b, " ", a) 上記コードで 30 200 と表示されるような。
[この投稿を含むスレッドを表示] [この投稿を削除]
[340] Re:「プログラミング言語を作る」
投稿者:(ぱ)
2007/02/20 02:13:25

>前橋さんもおっしゃってましたけど、DはCやJavaに比べて決定的にライブラリや >ツールが不足していて、言語仕様的には同等あるいは勝っているにも関わらず、 >ちょっと大き目のコードを書こうと思うととたんに苦しくなります。  なるほど。  でも、Cと比べれば、これだけ揃ってればまあそこそこ、という気もします。  http://www.kmonos.net/alang/d/phobos.html  GUIはWindowsのAPIを叩けるわけですよね。 >Java並みとはいわないまでも、Digital Marsにはもうちょっとがんばって、 >標準ライブラリをもう少し整えてもらいたいものです。  むむ。言語作りかけの身としてはプレッシャーです (^^;  言語そのものの機能が一通り揃ったら、鬼車でもくっつけるか、 いっそWindowsに特化してゲームとかを楽に作れる言語にしようか、とか 考えているところです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[339] 業務連絡:しばらく繋がらなかったようです
投稿者:(ぱ)
2007/02/20 02:13:25

 さっき私も、繋がらないなあ、と思っていたのですが、復旧したようです。  レンタルサーバ屋さんのお知らせより。 >上位回線プロバイダIDCの管理下にあるレイヤ3ファイアウォールルータの障害により、 >本日12:10頃より13:00頃の間、一時的にサーバーに接続できない状態となっておりま >した。 >現在は復旧いたしましたので、アクセス可能となっております。 >この度は障害によりご迷惑をお掛けし、誠に申し訳ございませんでした。
[この投稿を含むスレッドを表示] [この投稿を削除]
[338] Re:「プログラミング言語を作る」
投稿者:緒方
2007/02/20 02:13:25

>「フロンティア」は「あがり」なのか「ババをひく」係なのか… >いやその第三者的には是非ともがんばっていただきたく(ひでぇ) 前橋さんもおっしゃってましたけど、DはCやJavaに比べて決定的にライブラリやツールが不足していて、言語仕様的には同等あるいは勝っているにも関わらず、ちょっと大き目のコードを書こうと思うととたんに苦しくなります。 Java並みとはいわないまでも、Digital Marsにはもうちょっとがんばって、標準ライブラリをもう少し整えてもらいたいものです。
[この投稿を含むスレッドを表示] [この投稿を削除]