PPPUC++#9.5

7.7 Recovering from errors

  • エラーで終了していたけれど、それだと不便。
  • リカバリしましょ。
    • 1)例外を受ける 2)ゴミを片付けた後、反復 という戦略でいきます
  • さてこれまで try catchは main()にあったのだけれど、これではダメ
    • calculateの中、すなわち計算ループの中に組み込む必要があります。
  • で組み込む>
void calculate()
{
    while (cin)
    try {
       :
    }
    catch (exception& e) {
        cerr << e.what() << endl;
        clean_up_mess();
    }
}
  • さてこのclean_up_mess()はどう実装すべきか?
    • やる事は、入力ストリームから不要なトークンを吐き出せばオK
  • 戦略は二つ
    1. 一行全部捨てる
    2. エラーを出した式だけ選択的に捨てる
    • テストが楽になるのでここでは2番。つまりは次の ';' (セミコロン)まで読み飛ばす、という選択
  • 方法1:Token_stream::get() を使う方法。これで print = ';' が出るまでwhile()にて読み出す
    • しかしこれでは上手く行かないケースがある。" 1@z;" のように読み飛ばすゴミ情報中に非トークン(z)があった場合、 get()がさらに例外を出してしまう。
    • 結果、main()まで行ってしまい終了。これは扱いが面倒
      • まあ、リカバリ時のみの事なのでclean_up_mess()内で catchしても良いような気もしますが。。。
  • 困ったのでもう作戦会議
    • さっきのclean_up_mess()内でやる案が早速ダメだし。
      • 別に良いと思うんだけどなー
  • まあともかく、より奇麗な実装として Token_streamにignore()を実装
    • まあそりゃその方が良いよな
  • エラーの取り扱いは常にトリッキー
    • foolproofに!
    • マチュアは大抵そこまで気が回らない
  • 高品質なエラー処理ができたらプロフェッショナルの証

7.8 Variable

  • さて次は変数です。
    • pi,とかeとかの定数も欲しい
  • 大幅にコードを変更する事になる。こーゆーのはちゃんと理由があって、時間もたっぷりあるときにやるべき
    • ここでチャレンジするのは当然ながら、1)コードを見直す良い機会になる 2)更なるプログラミング技術を試す機会になる という理由

7.8.1 Variables and definitions

  • 記憶しておく(key, value)ペアが必要
class Variable {
public:
  string name;
  double value;
  Variable (string n, double v) :name(n), value(v) {} 
};
    • なんと、stringで持たせる、、、ということは線形探索ですか
  • もちろんそんな訳でvectorつかいます
  • get_value()は for でまわして if == してはる。なるほど。やっぱ mapつかっちゃダメなのか
    • ライブラリは積極的に使っていくんじゃなかったのだろうか
  • set_value()は既にあるヤツを探してそこに入れる。define_name()で新規登録。
  • 文法的には decraration()を追加して、" let hogehoge = 1234; " 、、、と言う感じ。
    • しかしソース冗長だなー。 is_declared()相当のコードが分散しています・・・短く書こうとして Cの呪いにかかるよりマシなのかな
  • あとはlexerに手を入れて、"let"を読み出せるようにするのと、それ以外の任意のalpha始まりalnum続きを変数として認識するように変更。
    • どうすんのかと思ってたらdefault: の中に if を入れる戦略できてた。まあ現実的か。
    • ちなみに各typeは let が 'L'で変数名が 'a' 
      • なんで'n'じゃないんだろうか。何故大文字なんだろうか、という謎が謎を・・・

7.8.3 Predefined names

  • さて、予定通り定数をつけませう。
  • piとか eとか
  • って、、、define_nameで入れるだけか。
    • じゃあ書き換え自由自在なんでは・・・><

7.8.4 Are we there yet?

ついた?

  • まだ
    • ありゃそうだ。まだ代入も作って無かった
    • と、そこでさっきの書き換え云々がでてくるのか。
  • 当初変数を入れるのを後回しにしたけど、やってみて貴方はどう感じるだろうか?
    1. 変数を使いするのは悪くない。大したコードの追加でもないし
    2. 変数を実装するのは、かなり重要な拡張だ。全関数をいじる必要があるし、全く新しい概念を追加する必要もある。計算機アプリのサイズの45%も増やしてしまったし、まだ全機能を実装できてないじゃん><
  • 初めての挑戦であれば2が普通だろう、という話。
  • 結局50%以上サイズ(or 複雑さ)を上昇させるものは新しいプログラムを書いているのと同じだと言うような話。そう考えるべき、とも。
    • 賛成です。逆に言うとだから複雑なプログラムを長い工期をかけて実装する事が「可能」なのだし