2012-09-08

SCIP in C++11 ― 2.4節その3


従業員データベースの構築と問題2.74

辞書的にはInsatiable enterprises, Inc.=「強欲社」とかなるか。
飽くことのない欲望という意味でアキナイ社という訳なのかな、飽きないと申しますし。

事業所名を型タグとして各従業員レコードに割り振って、
型ごとに情報を取り出す関数を自律制御させるわけで、、
つまりは複素数や問題2.73とあまり変わらない。

しかも集合の生成や要素探索は、すでに2.3.3節でひと通りのツールが出揃っているので、
思ったよりも楽。んで東京事業所とEU事業所を作り、
東京事業所は木で、EU事業所はリストで名簿を作ってあることにしたが、
それだけだとlookupが強力すぎて実装が変わらないので、
さらに、東京事業所はデータを従業員名キーで律儀にソートしてあるが、
EU事業所はソートしていないことにした。

問題2.74bget-recordの結果をさらに自律処理させるために、
get-recordが事業所情報も返さなければならない。
それにはlookupでヒットした事業所レコードに、事業所タグを付け直せば良い。

なおEU事業所の名簿で、ローマのカトーは本当はCatoだが、
加藤清正とダブらせるためにあえてKatoで押す。

----
typedef List Record;
typedef List BranchData;
typedef List HeadQuarterRecord;


class InsatiableInc{
public:
    InsatiableInc(const TagType tagIn):tagString(tagIn){}
    virtual ~InsatiableInc(void){};
    const TagType getTag(void)const{return(this->tagString);}

    virtual const Record getRecord
    (const BranchData&,const string&)const=0;
   
    virtual const int getSalary(const HeadQuarterRecord&)const=0;

    virtual const HeadQuarterRecord tag
    (const BranchData& branchData)const
    {return(attachTag(this->getTag(),branchData));}

private:
    const TagType tagString;
};


class TokyoBranch:public InsatiableInc{
public:
    TokyoBranch(void):InsatiableInc("Tokyo"){
        put("get-record",this->getTag(),
            makeLeaf(function<Record(BranchData,string)>
                     ([this](const BranchData& branchData,
                             const string& name)
                      {return(this->getRecord(branchData,name));})));
        put("get-salary",this->getTag(),
            makeLeaf(function<int(HeadQuarterRecord)>
                     ([this](const HeadQuarterRecord& record)
                      {return(this->getSalary(record));})));

    }
    const HeadQuarterRecord getRecord(const BranchData& branchList,
                           const string& name)const override
    {return(this->tag(lookup(name,branchList)));}
   
    const int getSalary(const HeadQuarterRecord& record)const override
    {
        if(isNull(cdr(record))){return(0);}
        return(value<int>(cadadr(record)));
    }

};

class EUBranch:public InsatiableInc{
public:
    EUBranch(void):InsatiableInc("EU"){
        put("get-record",this->getTag(),
            makeLeaf(function<Record(BranchData,string)>
                     ([this](const BranchData& branchData,
                             const string& name)
                      {return(this->getRecord(branchData,name));})));
        put("get-salary",this->getTag(),
            makeLeaf(function<int(HeadQuarterRecord)>
                     ([this](const HeadQuarterRecord& record)
                      {return(this->getSalary(record));})));

    }
    const HeadQuarterRecord getRecord(const BranchData& branchList,
                           const string& name)const override
    {return(this->tag(lookupUnordered(name,branchList)));}
   
    const int getSalary(const HeadQuarterRecord& record)const override
    {
        if(isNull(cdr(record))){return(0);}
        return(value<int>(caddr(record)));
    }

};

//---------abstraction barrier---------

InsatiableInc* _tokyoBranch(nullptr);

const void installTokyoBranch(void){
    _tokyoBranch=new TokyoBranch();
}

InsatiableInc* _EUBranch(nullptr);

const void installEUBranch(void){
    _EUBranch=new EUBranch();
}

const void uninstallBranches(void){
    if(nullptr!=_tokyoBranch) delete _tokyoBranch;
    if(nullptr!=_EUBranch) delete _EUBranch;
}

//---------abstraction barrier---------

const string branch(const BranchData branchData)
{return(value<string>(car(branchData)));}

const BranchData branchList(const BranchData& branchData)
{return(cdr(branchData));}

// get-record
const HeadQuarterRecord getRecord(const BranchData& branchData,
                                  const string& name)
{
    const List recordFunLeaf(get("get-record",branch(branchData)));
    if(isFunction(recordFunLeaf)){
        const auto recordFun
            (executable<Record,BranchData,string>(recordFunLeaf));
        return(recordFun(branchList(branchData),name));
    }
    return(0);
}

//get-salary
const int getSalary(const HeadQuarterRecord& record)
{
    const List salaryFunLeaf(get("get-salary",
                                 value<TagType>(car(record))));
    if(isFunction(salaryFunLeaf)){
        const auto salaryFun
            (executable<int,HeadQuarterRecord>(salaryFunLeaf));
        return(salaryFun(cdr(record)));
    }
    return(0);
}

//---------abstraction barrier---------

//find-employee-record
const List findEmployeeRecord
(const string& name,const List& allBranchList)
{
    const function<HeadQuarterRecord(BranchData)>
        getEmployeeRecords
        =[name](const BranchData& branchRecord)
        {return(getRecord(branchRecord,name));};
    return(mapping(getEmployeeRecords,allBranchList));
}


//make a list for Tokyo branch
const List addTokyoBranchMember
(const List& employeeList,
 const string name, const string address, const int salary)
{
    return(adjoinSet(makeList(name,makeList(address,salary)),employeeList));

}

const BranchData makeTokyoBranchEnployees(void){
    if(_tokyoBranch==nullptr){return(makeList());}

    List branchList(makeList());
    if(_tokyoBranch!=nullptr){
        branchList=addTokyoBranchMember
            (branchList,"Oda","Nadoya",20000);
        branchList=addTokyoBranchMember
            (branchList,"Toyotomi","Osaka",30000);
        branchList=addTokyoBranchMember
            (branchList,"Tokugawa","Edo",30000);
        branchList=addTokyoBranchMember
            (branchList,"Takeda","Kofu",10000);
        branchList=addTokyoBranchMember
            (branchList,"Kato","Kumamoto",12000);
    }
    return(_tokyoBranch->tag(branchList));
}

//make a list for EU branch
const List addEUBranchMember
(const List& employeeList,
 const string name, const string address, const int salary)
{
    return(adjoinSetUnordered(makeList(name,address,salary),employeeList));

}

const BranchData makeEUBranchEnployees(void){
    if(_EUBranch==nullptr){return(makeList());}

    List branchList(makeList());
    if(_EUBranch!=nullptr){
        branchList=addEUBranchMember
            (branchList,"Arthur","London",30000);
        branchList=addEUBranchMember
            (branchList,"Napolleon","Paris",20000);
        branchList=addEUBranchMember
            (branchList,"Siegfried","Berlin",10000);
        branchList=addEUBranchMember
            (branchList,"Kato","Roma",15000);
        branchList=addEUBranchMember
            (branchList,"Felipe","Madrid",12000);
       
    }
    return(_EUBranch->tag(branchList));
}



int main(int argc, char** argv)
{
    installTokyoBranch();
    const BranchData tokyoBranchList(makeTokyoBranchEnployees());
    installEUBranch();
    const BranchData EUBranchList(makeEUBranchEnployees());

    cout<<"tokyo-branch = "<<listString(tokyoBranchList)<<endl;
    cout<<"EU-branch = "<<listString(EUBranchList)<<endl;
    cout<<endl;

    const string name1("Toyotomi");
    const HeadQuarterRecord record1(getRecord(tokyoBranchList,name1));
    cout<<"(get-record tokyo-branch '"<<name1<<") = "
        <<listString(record1)<<endl;

    const string name2("Siegfried");
    const HeadQuarterRecord record2(getRecord(EUBranchList,name2));
    cout<<"(get-record EU-branch '"<<name2<<") = "
        <<listString(record2)<<endl;

    cout<<endl;
    cout<<"(get-salary (get-record Tokyo-branch '"<<name1<<")) = "
        <<getSalary(record1)<<endl;
    cout<<"(get-salary (get-record EU-branch '"<<name2<<")) = "
        <<getSalary(record2)<<endl;

    cout<<endl;
    const List allBranchList(makeList(tokyoBranchList,EUBranchList));
    cout<<"all-branch-list = (list tokyo-branch EU-branch)"<<endl;
    const string name3("Kato");
    cout<<"(find-employee-record "<<name3<<" all-branch-list) = "
        <<listString(findEmployeeRecord(name3,allBranchList))<<endl;


    uninstallBranches();
    return(0);
}
----
出力
----
tokyo-branch = ('Tokyo ('Kato ('Kumamoto 12000)) ('Oda ('Nadoya 20000)) ('Takeda ('Kofu 10000)) ('Tokugawa ('Edo 30000)) ('Toyotomi ('Osaka 30000)))
EU-branch = ('EU ('Felipe 'Madrid 12000) ('Kato 'Roma 15000) ('Siegfried 'Berlin 10000) ('Napolleon 'Paris 20000) ('Arthur 'London 30000))

(get-record tokyo-branch 'Toyotomi) = ('Tokyo 'Toyotomi ('Osaka 30000))
(get-record EU-branch 'Siegfried) = ('EU 'Siegfried 'Berlin 10000)

(get-salary (get-record Tokyo-branch 'Toyotomi)) = 30000
(get-salary (get-record EU-branch 'Siegfried)) = 10000

all-branch-list = (list tokyo-branch EU-branch)
(find-employee-record Kato all-branch-list) = (('Tokyo 'Kato ('Kumamoto 12000)) ('EU 'Kato 'Roma 15000))

0 件のコメント :

コメントを投稿