- 함수형 프로그래밍 예제연습.
1급함수, 순수함수, 메타프로그래밍, 람다, 메모이제이션 사용함.
<Memoizaion>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include <iostream> #include <functional> template<class T> class Memoization { private: T const & (*m_subRoutine)(Memoization *); mutable T m_recordedFunc; std::function<T()> m_func; static T const & ForceSubroutine(Memoization * d) { return d->DoRecording(); } static T const & FetchSubroutine(Memoization * d) { return d->FetchRecoding(); } T const & FetchRecoding() { return m_recordedFunc; } T const & DoRecording() { m_recordedFunc = m_func(); m_subRoutine = &FetchSubroutine; return FetchRecoding(); } public: Memoization(std::function<T()> func) : m_func(func), m_subRoutine(&ForceSubroutine), m_recordedFunc(T()) { } T Fetch() { return m_subRoutine(this); } }; | cs |
<Customer.h>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #ifndef __CUSTOMER_H__ #define __CUSTOMER_H__ #include <algorithm> #include <functional> #include <memory> #include <string> #include <vector> class Customer { private: template <typename T, typename U> class BaseClass { public: virtual U InvokeFunction(const std::shared_ptr<T> &) = 0; }; class CustomerName : public BaseClass<Customer, std::string> { public: virtual std::string InvokeFunction(const std::shared_ptr<Customer> &customer) { return customer->name; } }; class CustomerAddress : public BaseClass<Customer, std::string> { virtual std::string InvokeFunction(const std::shared_ptr<Customer> &customer) { return customer->address; } }; class CustomerPhoneNumber : public BaseClass<Customer, std::string> { virtual std::string InvokeFunction(const std::shared_ptr<Customer> &customer) { return customer->phoneNumber; } }; class CustomerEmail : public BaseClass<Customer, std::string> { virtual std::string InvokeFunction(const std::shared_ptr<Customer> &customer) { return customer->email; } }; public: // static std::vector<Customer> registerdCustomers; // 순수함수를 위해 삭제 int id = 0; std::string name; std::string address; std::string phoneNumber; std::string email; bool isActive = true; static std::vector<std::string> GetActiveCustomerNames(std::vector<Customer> customer); static std::vector<std::string> getActiveCustomerAddresses(std::vector<Customer> customer); static std::vector<std::string> GetActiveCustomerPhoneNumbers(std::vector<Customer> customer); static std::vector<std::string> GetActiveCustomerEmails(std::vector<Customer> customer); static int CountActiveCustomers(std::vector<Customer> customer); public: // std::vector<std::string> GetActiveCustomerByField(const std::string // &field); template <typename T> static std::vector<T> GetActiveCustomerByFunctionField( std::vector<Customer> customers, const std::shared_ptr<BaseClass<Customer, T>> &classField); };
#endif // __CUSTOMER_H__ | cs |
<Customer.cpp>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | #include "Customer.h" std::vector<std::string> Customer::GetActiveCustomerNames(std::vector<Customer> customer) { return Customer::GetActiveCustomerByFunctionField<std::string>( customer, std::make_shared<CustomerName>()); } std::vector<std::string> Customer::getActiveCustomerAddresses(std::vector<Customer> customer) { return Customer::GetActiveCustomerByFunctionField<std::string>( customer, std::make_shared<CustomerAddress>()); } std::vector<std::string> Customer::GetActiveCustomerPhoneNumbers(std::vector<Customer> customer) { return Customer::GetActiveCustomerByFunctionField<std::string>( customer, std::make_shared<CustomerPhoneNumber>()); } std::vector<std::string> Customer::GetActiveCustomerEmails(std::vector<Customer> customer) { return Customer::GetActiveCustomerByFunctionField<std::string>( customer, std::make_shared<CustomerEmail>()); } //재귀를 이용하여 성능향상 int Customer::CountActiveCustomers(std::vector<Customer> customer) { if (customer.empty()) return 0; else { int add = customer.front().isActive ? 1 : 0; customer.erase(customer.begin()); return add + CountActiveCustomers(customer); } //재귀실행 // int add = 0; // // for (auto cust : customer) { // if (cust.isActive) // ++add; // } // return add; } template <typename T> std::vector<T> Customer::GetActiveCustomerByFunctionField( std::vector<Customer> customers, // 등록된 객체를 매개변수로 받아 함수를 // 순수함수로 만들어 준다. const std::shared_ptr<BaseClass<Customer, T>> &classField) { std::vector<Customer> activeCustomers; std::vector<T> returnList; // 람다식을 이용하여 조건 필터링 std::copy_if(customers.begin(), customers.end(), std::back_inserter(activeCustomers), [](Customer customer) { if (customer.isActive) { return true; } else { return false; } }); // for (auto &customer : customers) { // if (customer.isActive) { // returnList.push_back( // classField->InvokeFunction(std::make_shared<Customer>(customer))); // } // } for_each(activeCustomers.begin(), activeCustomers.end(), [&returnList, &classField](Customer customer) { returnList.push_back(classField->InvokeFunction( std::make_shared<Customer>(customer))); }); return returnList; } // 1급함수의 사용 // std::vector<std::string> // Customer::GetActiveCustomerByField(const std::string &field) { // std::function<std::string(const Customer &, Customer)> funct; // // if (field == "name") { // funct = &Customer::GetActiveCustomerNames; // } else if (field == "address") { // funct = &Customer::getActiveCustomerAddresses; // } else if (field == "phoneNumber") { // funct = &Customer::GetActiveCustomerPhoneNumbers; // } else if (field == "email") { // funct = &Customer::GetActiveCustomerEmails; // } else { // throw std::invalid_argument("Unknown field"); // } // // return GetActiveCustomerByFunctionField(funct); // } | cs |
아직도 함수형 프로그래밍이 뭔지 모르겠음....
출처 : 모던 C++로 배우는 함수형 프로그래밍 위스누 앤거로 저, 김현욱 옮김