- 함수형 프로그래밍 예제연습.


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++로 배우는 함수형 프로그래밍  위스누 앤거로 저, 김현욱 옮김

+ Recent posts