2012-09-27

SCIP in C++11 ― 3.1.3節


銀行口座その3:共同口座と問題3.7

3.1.1で、各銀行口座のbalanceオブジェクトをどのように保持しているのか、
C++11でもSchemeでも見づらくて気持ち悪い、という経験をしたが、
たしかにそれはバグの温床だわな。
普段のプログラムでも、オブジェクトをコロコロ変更すると訳がわからなくなるので、
なるべく一度インスタンス化したオブジェクトは変えないようなスタイルを、
なんとなく意識していたが、それが正しいのだ、ということ。

ただ、そうできたのは、そうできる問題に対することが多かったから、
ということにすぎない。データベースとか扱ったときはだいぶ混乱したこともある。
その辺をどう頑健にしていくかが3章の一つのテーマなのかな。

問題3.8Schemeの話なのでパス。

----
const function<List(List)> returnErrorMessage
=[](const List& Dummy){
    return(makeLeaf("Incorrect password"));
};

const function<List(List)> returnErrorMonitored
(makeMonitored(makeLeaf(returnErrorMessage)));

const function<List(List)> callTheCops
=[](const List& Dummy){
    return(makeLeaf("The cops are called."));
};

const function<List(List)> processError(const List& limitCount)
{
    if(returnErrorMonitored
       (makeLeaf("how-many-calls?"))>=limitCount-makeLeaf(1))
     {return(callTheCops);}
    return(returnErrorMonitored);
}

const function<function<List(List)>(List,List)> makeAccount
(const List& balanceIn, const List& passwdIn)
{

    const List&& balance(std::move(balanceIn));
    const List&& passwd(std::move(passwdIn));
    const List limitCount(makeLeaf(7));

    const function<List(List)> withdraw
     =[balance](const List& amount){
     if(balance>=amount){
         setInsert(balance-amount,balance);
         return(balance);
     }
     return(makeLeaf("Insuffcient funds"));
    };
   
    const function<List(List)> deposit
     =[balance](const List& amount){
     setInsert(balance+amount,balance);
     return(balance);
    };

    const function<function<List(List)>(void)> processErrorMessage
     =[limitCount](void){
     return(processError(limitCount));
    };

    const function<function<List(List)>(List,List)> dispatch=
     [withdraw,deposit,processErrorMessage,passwd,limitCount]
     (const List& passwdInput, const List& message){
     if(isEq(message,makeLeaf("error"))
        ||!isEq(passwd,passwdInput)){return(processErrorMessage());}
     returnErrorMonitored(makeLeaf("reset-count"));
     if(isEq(message,makeLeaf("withdraw"))){return(withdraw);}
     if(isEq(message,makeLeaf("deposit"))){return(deposit);}
     cerr<<"Unknown request --- MAKE-ACCOUNT"<<endl;
     exit(1);
     return(function<List(List)>([](const List& i){return(makeList());}));
    };
    return(dispatch);
}

const function<function<List(List)>(List,List)> makeJoint
(const function<function<List(List)>(List,List)>& oldAccountIn,
 const List& oldPasswdIn, const List& jointAccountPasswdIn)
{
    const function<function<List(List)>(List,List)>&&
     oldAccount(std::move(oldAccountIn));
    const List&& oldPasswd(std::move(oldPasswdIn));
    const List&& jointAccountPasswd(std::move(jointAccountPasswdIn));

    const function<function<List(List)>(List,List)> dispatch
     =[oldAccount,oldPasswd,jointAccountPasswd]
     (const List& passwdInput, const List& message){
     if(!isEq(jointAccountPasswd,passwdInput)){
         return(oldAccount(makeLeaf(""),makeLeaf("error")));
     }
     return(oldAccount(oldPasswd,message));
    };
    return(dispatch);
}

int main(int argc, char** argv)
{
    cout<<"Excersize 3.7:"<<endl;
    const auto peterAccount
     (makeAccount(makeLeaf(100),makeLeaf("open-sesame")));
    cout<<"peter-acc = (make-account 100 'open-sesame)"<<endl;
    cout<<"((peter-acc 'open-sesame 'withdraw) 40) = "
     <<listString(peterAccount
                  (makeLeaf("open-sesame"),
                   makeLeaf("withdraw"))(makeLeaf(40)))<<endl;
    cout<<"((peter-acc 'hirake-goma 'deposit) 40) = "
     <<listString(peterAccount
                  (makeLeaf("hirake-goma"),
                   makeLeaf("deposit"))(makeLeaf(40)))<<endl;
   
    const auto paulAccount
     (makeJoint(peterAccount,
                makeLeaf("open-sesame"),makeLeaf("rosebud")));
    cout<<endl<<"paul-acc = (make-joint peter-acc 'open-sesame 'rosebud)"<<endl;
    cout<<"((paul-acc 'rosebud 'withdraw) 40) = "
     <<listString(paulAccount
                  (makeLeaf("rosebud"),
                   makeLeaf("withdraw"))(makeLeaf(40)))<<endl;
    cout<<"((paul-acc 'open-sesame 'deposit) 40) = "
     <<listString(paulAccount
                  (makeLeaf("open-sesame"),
                   makeLeaf("deposit"))(makeLeaf(40)))<<endl;
    cout<<"((paul-acc 'rosebud 'deposit) 100) = "
     <<listString(paulAccount
                  (makeLeaf("rosebud"),
                   makeLeaf("deposit"))(makeLeaf(100)))<<endl;
    cout<<"((peter-acc 'open-sesame 'deposit) 40) = "
     <<listString(peterAccount
                  (makeLeaf("open-sesame"),
                   makeLeaf("deposit"))(makeLeaf(40)))<<endl;

    return(0);
}
----
出力
----
Excersize 3.7:
peter-acc = (make-account 100 'open-sesame)
((peter-acc 'open-sesame 'withdraw) 40) = 60
((peter-acc 'hirake-goma 'deposit) 40) = Incorrect password

paul-acc = (make-joint peter-acc 'open-sesame 'rosebud)
((paul-acc 'rosebud 'withdraw) 40) = 20
((paul-acc 'open-sesame 'deposit) 40) = Incorrect password
((paul-acc 'rosebud 'deposit) 100) = 120
((peter-acc 'open-sesame 'deposit) 40) = 160

0 件のコメント :

コメントを投稿