パスワードを忘れた? アカウント作成
190352 journal

quaternionの日記: 特殊なC言語入門 7

日記 by quaternion
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • by okky (2487) on 2010年02月04日 14時34分 (#1713748) ホームページ 日記

    完成したら、順番どおりにポイントするようなページをどこかに作ってください。Blogが逆順になるのはやむを得ませんが、連続表示しておいて真ん中に違う記事があったりすると、「あぁ、これは関係ないんだ」とスキップした拍子に、短いものもスキップしてしまう。「3」とか。各記事ごとに表示するリンク集があれば、タブで全部一気に開いて、順番に読む、と言う手が使える。

    i++が駄目だと言う割には ++i を使っている。 i+=1; と書くべきなら、++i だって i+=1 にするべきじゃない?特に「8」の例は i++ だろうが ++i だろうが関係ないんだし。

    逆に言おう。i++ や ++i は止めるべきではない。それらは 「アセンブラを教える時に」大事な概念だ(つーか論理回路を理解するときに大事)。
    C言語に限らないが、あるプログラミング言語は、そのプログラミング言語だけを教える事だけしか念頭におかない、という状態であってはいけない。たとえば、C++でいうメソッドはどのように実装されるのか? これをいきなりアセンブラレベルで教えるのは辛い。なので C言語のような「中間のレベル」を理解したほうが良い。アセンブラも計算機のマイクロや論理回路を理解するうえでは重要なヒントを与えてくれる。この手の「レベルアップ」は500日~600日ぐらい毎に行うと良いのだがこれぐらいだと「1つ前に教わった時に刷り込まれた内容」が一部邪魔をしたり、逆に補助になったりする。プログラミング言語入門はそのあたりまで考慮してかかれるべきだと思う。

    --
    fjの教祖様
  • by Anonymous Coward on 2010年02月04日 21時00分 (#1713887)

    まずはつまらないことで申し訳ありませんが、typoの指摘。

    • 2のコードのいくつかで"const"が"cost"になっています。

    あと、C++でSchemeのマイ処理系を作成中の日曜プログラマの私が思うところをいくつか。Cに関しては、本格的なプログラムを書いたことがないですし、職業プログラマでもありませんので、あまり深くは気にしないでください。

    • switchは落とし穴がありますが、switchで書けば、条件の対象が1つであることが明確ですし、ifを連ねるよりも、処理が速そうな気がします。これは気のせい?
    • doは使うこともあるような。ただ、whileでも必ず1回は処理されることを保証すれば、同じことなので、いらないと言われればそうなので、使わないのがいいのかな。
    • whileの条件式に1を入れることも、ループを抜けるタイミングが複数あり、それぞれの異なる後処理が必要な場合は、ifで脱出の際の処理を書くというやり方になるので、ありうる事だと思います。
    • whileの条件式が定数でなかったとしても、無限ループにならないと言う保証はないわけですし、結局のところ、ループ内の処理の先頭にifを書くぐらいなら、whileに条件式を書いた方が簡単かつ分かりやすいというだけであって、別途、脱出条件を書かなければいけないのであれば、条件式に定数もありだと思います。
    • breakに関しては、多重ループを考慮したとしても、使用を避ける理由はあまりないような気がします。抜けるループは所詮、1つに過ぎませんし、breakを使わなければループ毎の判定処理が1個増やさないといけない場合もあるわけで、処理速度に影響が出るように思います。ループを途中で中断し、whileの条件式に使われている変数の値を利用したいとき、その変数の値は書き換えられないので、ifとbreakで書くのが分かりやすいように思います。
    • breakというのは関数の呼び出しとは違い、戻り値があるわけでもなく、ブロックの外に出ると言うジャンプ命令の一種なので、関数型の発想では避けるべきものなのでしょう。とは言え、ループ自体がジャンプ命令なので、再帰で書かない限り、手続き型の発想は残ります。問題は、目的を明確化しづらいgotoの使用であって、ブロックの外に出ると言う目的が明確なbreakは良いのではないかと思います。むしろ、ループの終了条件を満たすように変数の値を変える方が、コメントをつけておかない限り、意図が読みにくい気がします。
    • インクリメント、デクリメントに関しては、機械語レベルにおいて、ただの加算、減算とはわけが違うので、代入よりも速いのではないかと思ったりもします。整数型のある変数の値が0であることが保証されているような場合において、1を代入したいときでさえ、インクリメントの方が速いのではないかと思ったりします。可読性のために、意味的にインクリメントでないときはインクリメントは使いませんが。
    • ありがとうございます.
      • タイポ:訂正させていただきました.まだあるかもしれません.見つけ次第訂正させていただきます.
      • switch文について:条件の対象がひとつであることを明示できるのはswitch文のうまみと思います.switch文が(Modula-2のように)勝手にbreakしない落とし穴とどちらをとるかですね.生成されるコードはgcc2のころから変わらなかったように記憶しています.(生成されるコードについて確認をしていないので,間違っているかもしれません.)
      • do文について:doは条件式を見落としがちなので,使うことには反対の立場を取っています.
      • while(1)あるいはwhile(定数式)について:while(1)の必要性に同意します.イベントドリブン処理のランループはwhile(1)ですね.ここでは,while(1)としか書けないような処理は本来環境(ランタイムライブラリ)側が面倒を見てくれないと困るという立場を取っています.もちろん環境側のコーディングにはwhile(1)が必要です.プログラムの完備性から言えばwhile(1)を認めてあげるべきかもしれませんね.検討してみます.
      • breakについて:breakは実を言えば僕も多用していました.この「入門」では出来るだけ関数型に近いスタイルでプログラムを書いてもらいたいという裏の意図があるので,あえてbreakは使うなと書きました.いずれ,項を改めて書かねばならないテーマかもしれません.
      • gotoについて:僕はgotoよりも(goto先の)ラベルのほうが可読性の問題を引き起こしていると思います.gotoは飛び先が明示されますが,ラベルはどこから飛んできたのか(ラベルを見ただけでは)わからないからです.
      • インクリメント,デクリメントについて:i += 1 はコンパイラによって簡単に最適化できますので,あえてインクリメントの代わりに i += 1 を使えと書きました.(手元の i686-apple-darwin9-gcc-4.0.1 で確認したところ i += 1 と ++i は全く同じコードへコンパイルされました.)ただし,C++言語でイテレータを実装する場合単項インクリメント・デクリメントのみ実装する(あるいはスペシャルケースとして実装される)ケースが十分考えられますから,単項インクリメント・デクリメント演算子は必要なものと認識しています.いずれ単項インクリメント・デクリメント演算子については記述するつもりです.

      コメントをいただけて大変嬉しく思っています.ありがとうございます.

    • ところで,Scheme on C++ ですか!! プロジェクトページなどあれば是非お知らせください.
      • by Anonymous Coward
        恥ずかしいので勘弁してください。素人もろ出しなんですから。ツッコミどころ満載。

        dynamic-windとかも一旦は仕様通りに動作するようにしたのですが、参照カウントを導入してから完全な動作をしてなかったように思います。Scheme仕様上の例外処理も基本的なところはできているものの、組み込みの手続き(関数)を対応させていなかったりします。また、phaseという概念を理解しないまま自己流の解釈で始めてしまったため、一旦、書き終えたlet、let*、letrec、letrec*を書き直す羽目になりました。そのため、letrecが使えない状態に戻ってしまいました。

        その状況
typodupeerror

人生unstable -- あるハッカー

読み込み中...