C++ ile fonksiyonel programlamanın olayını kavramak adına . a+b+c işlemini döndürecek olan f (a) (b) (c) methodlarını yapmaya çalışalım.
F fonksiyonu, operator() den nesneyi döndürerek yapabilirsiniz. İşte bunu yapmanın bir yolu:
1 2 3 4 5 6 7 8 9 10 11 |
struct sum { double val; sum(double a) : val(a) {} sum operator()(double a) { return val + a; } operator double() { return val; } }; sum f(double a) { return a; } |
Kullanımı
1 |
int main() { std::cout << f(1)(2)(3)(4) << std::endl; } |
Diğer bir yol Template versiyonu : Derleyicinin türe ait olmasına izin verecek bir şablonlu sürüm bile yazabilirsiniz. (Tür belirleme süreci şablon işlemlerindeki gibi yürütülmektedir. (Eğer bu sürecin ayrıntılarıyla ilgileniyorsanız standartlarda belirtilen Template Argument Deduction işlemlerini incelemelisiniz.) )
Denemesi bedava.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
template <class T> struct sum { T val; sum(T a) : val(a) {} template <class T2> auto operator()(T2 a) -> sum<decltype(val + a)> { return val + a; } operator T() { return val; } }; template <class T> sum<T> f(T a) { return a; } |
İşte biraz farklı bir yaklaşım, *this this operatorden bir referansı döndürür, dolayısıyla aktarılan kopyalarınız yoktur. Recursive olarak kendisine depolayan bir funktor‘un çok basit bir uygulamasıdır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <iostream> template <typename T> class Sum { T x_{}; public: Sum &operator()(T x) { x_ += x; return *this; } operator T() const { return x_; } }; int main() { Sum<int> s; std::cout << s(1)(2)(3); } |
Bunu yapmanın en kolay başka bir yolu, plus2() ile ilgili olarak plus3() tanımlamaktır.
Bu, ilk iki argüman listesini plus2()’yi çağırmak için kullanılan tek bir arglist’e birleştirir.
Bunu yapmak, önceden var olan kodumuzu en az tekrarlama ile tekrar kullanmamıza izin verir ve gelecekte kolaylıkla genişletilebilir; PlusN() sadece plusN(1) çağıran bir lambda döndürmelidir, plus2()’ye ulaşana kadar çağrıyı önceki işleve sırayla geçirecektir.
Bu şekilde kullanılabilir:
1 2 3 4 5 6 7 8 9 10 |
std::function<double(double)> plus2(double a) { return [a](double b) { return a + b; }; } auto plus3(double a) { return [a](double b) { return plus2(a + b); }; } int main() { std::cout << plus2(1)(2) << ' ' << plus3(1)(2)(3) << '\n'; } // Output: 3 6 |
Bunu kolayca ek fonksiyonlar için oluşturmamız gereken bir template function haline getirebiliriz.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
template <int N> auto plus(double a); template <int N> auto plus(double a) { return [a](double b) { return plus<N - 1>(a + b); }; } template <> auto plus<1>(double a) { return a; } int main() { std::cout << plus<2>(1)(2) << ' ' << plus<3>(1)(2)(3) << ' ' << plus<4>(1)(2)(3)(4) << ' ' << plus<5>(1)(2)(3)(4)(5) << '\n'; } // Output: 3 6 10 15 |