C ++ 14 рдореЗрдВ рдХрд░реА рдФрд░ рдЖрдВрд╢рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдЖрдкрдХреЛ C ++ рдореЗрдВ рдПрдХ рдХрд░реАрдиреЗ рдХреЗ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЖрдВрд╢рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ рдЬреЛ рдХрд┐ рдореЗрд░рд╛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдкрд╕рдВрджреАрджрд╛ рд╣реИред рдореИрдВ рдЗрд╕ рдЪреАрдЬрд╝ рдХрд╛ рдЕрдкрдирд╛ рдкрд╛рдпрд▓рдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рднреА рджрд┐рдЦрд╛рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдЬрдЯрд┐рд▓ рдЧрдгрд┐рддреАрдп рд╕реВрддреНрд░ рдХреЗ рдмрд┐рдирд╛ рдХрд░реАрдиреЗ рдХреА рдмрд╛рдд рд╕рдордЭрд╛рддрд╛ рд╣реВрдВ, рдЬрд┐рд╕рд╕реЗ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрдкрдХреЗ рд▓рд┐рдП рд╕рд░рд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдо рдпрд╣ рднреА рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ kari.hpp рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╣реБрдб рдХреЗ рдиреАрдЪреЗ рдХреНрдпрд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рдХрд░реА рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд░реЗрдВрдЧреЗред рд╡реИрд╕реЗ рднреА, рдЕрдВрджрд░ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЖрдХрд░реНрд╖рдХ рд╕рд╛рдорд╛рди рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИ!


Currying


рддреЛ, рдХрд░реА рдХреНрдпрд╛ рд╣реИ? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЙрди рд╢рдмреНрджреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ рдЬреЛ рдЖрдк рд╣рд╛рд╕реНрдХреЗрд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд╕реЗ рд╣рд░ рд╕рдордп рд╕реБрдирддреЗ рд╣реИрдВ ( рдореЛрдирд╛рдб рдХреЗ рдмрд╛рдж, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ)ред рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ, рд╢рдмреНрдж рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЬреЛ рдкрд╛рдардХ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдордПрд▓ рдкреНрд░рдХрд╛рд░ рдХреА рднрд╛рд╖рд╛рдУрдВ рдпрд╛ рд╣рд╛рд╕реНрдХреЗрд▓ рдкрд░ рд▓рд┐рдЦ рдЪреБрдХреЗ рд╣реИрдВ, рдпрд╛ рдЬреЛ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕рдХрд╛ рдЕрдиреНрдпрддреНрд░ рд╕реЗ рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИ, рдЗрд╕ рдЕрдиреБрднрд╛рдЧ рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВред


рдХреНрдпреВрд░рд┐рдВрдЧ - рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдмрджрд▓рдиреЗ рдХреА рддрдХрдиреАрдХ рд╣реИ рдЬреЛ рдПрди рддрд░реНрдХреЛрдВ рдХреЛ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд▓реЗ рдЬрд╛рддреА рд╣реИ, рдЬреЛ рдПрдХ рддрд░реНрдХ рд▓реЗрддреА рд╣реИ рдФрд░ рдЕрдЧрд▓реЗ рддрд░реНрдХ рдХреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреА рд╣реИ, рдФрд░ рдпрд╣ рддрдм рддрдХ рдЪрд▓рддреА рд╣реИ рдЬрдм рддрдХ рдХрд┐ рд╣рдо рдЕрдВрддрд┐рдо рддрд░реНрдХ рдХреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╡рд╛рдкрд╕ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реИ рд╕рдордЧреНрд░ рдкрд░рд┐рдгрд╛рдоред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдорджрдж рдХрд░рддрд╛ рд╣реИ рдЕрдЧрд░ рдореИрдВ рдЖрдкрдХреЛ рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛рддрд╛ рд╣реВрдВ:


int sum2(int lhs, int rhs) { return lhs + rhs; } 

рдпрд╣рд╛рдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдмрд╛рдЗрдирд░реА рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝рдВрдХреНрд╢рди рд╣реИред рдФрд░ рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рд╣рдо рдЗрд╕реЗ рд╕рд┐рдВрдЧрд▓ рд╡реЗрд░рд┐рдПрдмрд▓ рдлрдВрдХреНрд╢рди рдореЗрдВ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ? рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ:


 auto curried_sum2(int lhs) { return [=](int rhs) { return sum2(lhs, rhs); }; } 

рдирд╣реАрдВ, рд╣рдордиреЗ рдХреНрдпрд╛ рдХрд┐рдпрд╛? рд╣рдордиреЗ рд▓реИрдореНрдмрдбрд╛ рдирд╛рдордХ рдПрдХ рдПрдХрд▓ рддрд░реНрдХ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдореВрд▓реНрдп рд▓рд┐рдпрд╛ рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рджреВрд╕рд░рд╛ рддрд░реНрдХ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдЦреБрдж рдХреЛ рдЬреЛрдбрд╝ рд▓реЗрддрд╛ рд╣реИред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдо рдПрдХ-рдПрдХ рдХрд░рдХреЗ рдЕрдкрдиреЗ рддрд░реНрдХреЛрдВ рдХреЗ рд▓рд┐рдП curried_sum2 рдлрдВрдХреНрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 // output: 42 std::cout << sum2(40, 2) << std::endl; std::cout << curried_sum2(40)(2) << std::endl; 

рдФрд░ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд░реА рдСрдкрд░реЗрд╢рди рдХрд╛ рдкреВрд░рд╛ рдмрд┐рдВрджреБ рд╣реИред рдмреЗрд╢рдХ, рдпрд╣ рдХрд┐рд╕реА рднреА рдХрд╛рд░реНрдп рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ - рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдЙрд╕реА рддрд░рд╣ рдХрд╛рдо рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рд╣рд░ рдмрд╛рд░ рдЬрдм рд╣рдо рдХрд┐рд╕реА рджреВрд╕рд░реЗ рддрд░реНрдХ рд╕реЗ рдореВрд▓реНрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдПрди -1 рддрд░реНрдХреЛрдВ рдХрд╛ рдПрдХ рдХрд░реАрдмреА рдХрд╛рд░реНрдп рд▓реМрдЯрд╛рдПрдВрдЧреЗ:


 auto sum3(int v1, int v2, int v3) { return v1 + v2 + v3; } auto curried_sum3(int v1) { return [=](int v2){ return [=](int v3){ return sum3(v1, v2, v3); }; }; } // output: 42 std::cout << sum3(38, 3, 1) << std::endl; std::cout << curried_sum3(38)(3)(1) << std::endl; 

рдЖрдВрд╢рд┐рдХ рдЖрд╡реЗрджрди


рдЖрдВрд╢рд┐рдХ рдЖрд╡реЗрджрди - рдПрди рддрд░реНрдХреЛрдВ рдХреЗ рдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ рдЬрдм рд╡реЗ рдХреЗрд╡рд▓ рддрд░реНрдХреЛрдВ рдХрд╛ рдПрдХ рд╣рд┐рд╕реНрд╕рд╛ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рд╢реЗрд╖ рддрд░реНрдХреЛрдВ рдХрд╛ рдПрдХ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВред


рдЗрд╕ рд╕рдВрдмрдВрдз рдореЗрдВ рдпрд╣ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рд╣рд╛рд╕реНрдХреЗрд▓ рдЬреИрд╕реА рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреА рдкреАрда рдХреЗ рдкреАрдЫреЗ рдпрд╣ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИред рд╣рдо рдпрд╣рд╛рдВ рдХреНрдпрд╛ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкреНрд░рджрд░реНрд╢рди рдХрд░рдирд╛ рд╣реИ, sum3 рд╣рдорд╛рд░реЗ sum3 рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмреБрд▓рд╛рдирд╛ рд╣реИ: sum3(38,3)(1) рдпрд╛ рд╢рд╛рдпрдж рдЗрд╕ рддрд░рд╣: sum3(38)(3,1) ред рдЙрд╕рдХреЗ рд╢реАрд░реНрд╖ рдкрд░, рдпрджрд┐ рдХреЛрдИ рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдХреНрдпреВрд░реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рдкрд╣рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рддрд░реНрдХреЛрдВ рдХреА рд╕реВрдЪреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рднреА рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЖрдЗрдП рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВ:


 int boo(int v1, int v2) { return v1 + v2; } auto foo(int v1, int v2) { return kari::curry(boo, v1 + v2); } // output: 42 std::cout << kari::curry(foo)(38,3,1) << std::endl; std::cout << kari::curry(foo)(38,3)(1) << std::endl; std::cout << kari::curry(foo)(38)(3,1) << std::endl; 

рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣рд╛рдБ рдЕрдкрдиреЗ рдЖрдк рд╕реЗ рдереЛрдбрд╝рд╛ рдЖрдЧреЗ рдирд┐рдХрд▓ рдЧрдП рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП kari.hpp рдЙрдкрдпреЛрдЧ, рдЗрд╕рд▓рд┐рдП рд╣рд╛рдБ, рдпрд╣ рдРрд╕рд╛ рдХрд░рддрд╛ рд╣реИред


рд▓рдХреНрд╖реНрдп рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛


рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдХреБрдЫ рд▓рд┐рдЦреЗрдВ, рдпрд╣ рд╕рдордЭрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ (рдпрд╛ рд╡рд╛рдВрдЫрдиреАрдп) рдХрд┐ рд╣рдо рдЖрдЦрд┐рд░ рдореЗрдВ рдХреНрдпрд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдФрд░ рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рд╕реА рднреА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрд░реА рдФрд░ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рдорд┐рд▓реЗ рдЬрд┐рд╕реЗ C ++ рдореЗрдВ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЬреЛ рд╣реИрдВ:


  • рд▓рдВрдмреЛрджрд░ (рд╕рд╛рдорд╛рдиреНрдп рд╡рд╛рд▓реЗ рд╕рд╣рд┐рдд)
  • рдлрд╝рдВрдХреНрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ (рдлрд╝рдВрдХреНрд╢рдирд▓рд░реНрд╕)
  • рдХрд┐рд╕реА рднреА рдХрд╛рд░реНрдп рдХреЗ рдХрд╛рд░реНрдп (рдЯреЗрдореНрдкреНрд▓реЗрдЯ рд╕рд╣рд┐рдд)
  • рдкрд░рд┐рд╡рд░реНрддрди рд╕рдВрдмрдВрдзреА рдХрд╛рд░реНрдп
  • рдПрдХ рдХрдХреНрд╖рд╛ рдХреЗ рддрд░реАрдХреЗ

рд╡рд░реАрдбрд┐рдХ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдкрд░ рдХрд░реАрдиреЗ рдХреА рддрд░реНрдХреЛрдВ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдХреЗ рд╣рдо рдкрд░ рдЕрдВрдХреБрд╢ рд▓рдЧрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред Std :: bind рдФрд░ рдЗрд╕рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЗ рд╕рд╛рде рдорд╛рдирдХ рд╕рд╣рднрд╛рдЧрд┐рддрд╛ рднреА рд╡рд╛рдВрдЫрдиреАрдп рд╣реИред рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рд╣рдореЗрдВ рдХрдИ-рдЪрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдФрд░ рдиреЗрд╕реНрдЯреЗрдб рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд╡рд╕рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдРрд╕рд╛ рд▓рдЧреЗ рдХрд┐ рд╣рдо рдПрдХ рдШреБрдорд╛рд╡рджрд╛рд░ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВред


рдФрд░ рд╣рдореЗрдВ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреА рдирд╣реАрдВ рднреВрд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдореЗрдВ рд░реИрдкрд░ рдХреА рдХрдореНрдкреНрдпреВрдЯреЗрд╢рдирд▓ рд▓рд╛рдЧрдд, рддрд░реНрдХреЛрдВ рдХреЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рдФрд░ рдЙрдирдХреЗ рднрдВрдбрд╛рд░рдг рдХреЛ рдХрдо рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдирдХрд▓ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЖрдЧреЗ рдмрдврд╝рдирд╛ рд╣реИ, рдХреЗрд╡рд▓ рдЙрд╕реА рдЪреАрдЬрд╝ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ рдЬреЛ рд╣рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЬрд┐рддрдирд╛ рд╕рдВрднрд╡ рд╣реЛ рдЙрддрдирд╛ рддреЗрдЬрд╝реА рд╕реЗ рдбреЗрдЯрд╛ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░реЗрдВ (рдЖрдЧреЗ рдирд┐рдХрд╛рд▓реЗрдВ)ред


рд▓реЗрдЦрдХ, рдЖрдк std::bind рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ std::bind рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рд╕реЗ std::bind !


рд╣рд╛рдБ, рдФрд░ рдирд╣реАрдВред std::bind рдирд┐рд╕реНрд╕рдВрджреЗрд╣ рдПрдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдФрд░ рд╕рд┐рджреНрдз рдЙрдкрдХрд░рдг рд╣реИ, рдФрд░ рдореИрдВ рдЗрд╕рдХрд╛ рдХрд╛рддрд┐рд▓ рдпрд╛ рд╡рд┐рдХрд▓реНрдк рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ред рд╣рд╛рдБ, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реА рдФрд░ рд╕реНрдкрд╖реНрдЯ рдЖрдВрд╢рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдпрд╣ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рдХрд┐ рд╣рдо рдХреНрдпрд╛ рддрд░реНрдХ рджреЗ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ рдХрд╣рд╛рдБ, рдФрд░ рдХрд┐рддрдиреЗ)ред рд▓реЗрдХрд┐рди рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рд╣реИ рдХрд┐ рдпрд╣ рд╕рдмрд╕реЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдирд╣реАрдВ рд╣реИ, рдпрд╣ рдЙрд▓реНрд▓реЗрдЦ рдирд╣реАрдВ рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╣рдореЗрд╢рд╛ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреА рдпреЛрдЧреНрдпрддрд╛ рдХреЛ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЙрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


 int foo(int v1, int v2, int v3, int v4) { return v1 + v2 + v3 + v4; } // std::bind auto c0 = std::bind(foo, _1, _2, _3, _4); auto c1 = std::bind(c0, 15, _1, _2, _3); auto c2 = std::bind(c1, 20, 2, _1); auto rr = c2(5); std::cout << rr << std::endl; // output: 42 // kari.hpp auto c0 = kari::curry(foo); auto c1 = c0(15); auto c2 = c1(20, 2); auto rr = c2(5); std::cout << rr << std::endl; // output: 42 

рдПрдкреАрдЖрдИ


 namespace kari { template < typename F, typename... Args > constexpr decltype(auto) curry(F&& f, Args&&... args) const; template < typename F, typename... Args > constexpr decltype(auto) curryV(F&& f, Args&&... args) const; template < std::size_t N, typename F, typename... Args > constexpr decltype(auto) curryN(F&& f, Args&&... args) const; template < typename F > struct is_curried; template < typename F > constexpr bool is_curried_v = is_curried<F>::value; template < std::size_t N, typename F, typename... Args > struct curry_t { template < typename... As > constexpr decltype(auto) operator()(As&&... as) const; }; } 



kari::curry(F&& f, Args&&... args)


рд╡реИрдХрд▓реНрдкрд┐рдХ рдлрд╝рдВрдХреНрд╢рди curry_t рд╕рд╛рде рдпрд╛ рджрд┐рдП рдЧрдП рдлрд╝рдВрдХреНрд╢рди f рдХреЗ рд▓рд┐рдП рддрд░реНрдХреЛрдВ рдХреЗ рдЖрд╡реЗрджрди рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЗ рд╕рд╛рде curry_t рдкреНрд░рдХрд╛рд░ (рдПрдХ рдХрд░реА рдлрд╝рдВрдХреНрд╢рди) рдХрд╛ рдлрд╝рдВрдХреНрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рд▓реМрдЯрд╛рддрд╛ рд╣реИ (рдлрд╝рдВрдХреНрд╢рди рдлрд╝рдВрдХреНрд╢рди рд╢реВрдиреНрдп рд╣реИ, рдпрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдП рдЧрдП рддрд░реНрдХ рдЗрд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдереЗ)ред


рдпрджрд┐ f рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рд╡рд╣ рдлрд╝рдВрдХреНрд╢рди рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рд╡рд╣ рдЕрдкрдиреА рдХреЙрдкреА рдХреЛ рджрд┐рдП рдЧрдП рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред




kari::curryV(F&& f, Args&&... args)


рдЪрд░ рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд░реАрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ () рдСрдкрд░реЗрдЯрд░ рдмрд┐рдирд╛ рдХрд┐рд╕реА рддрд░реНрдХ рдХреЗред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


 auto c0 = kari::curryV(std::printf, "%d + %d = %d"); auto c1 = c0(37, 5); auto c2 = c1(42); c2(); // output: 37 + 5 = 42 

рдпрджрд┐ f рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреНрдпреВрд░реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рд╡рд╣ рдЕрдкрдиреА рдХреЙрдкреА рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕ рддрд░рд╣ рдХреЗ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдкрд░рд┐рд╡рд░реНрддрди рдХрд┐рдП рдЧрдП рддрд░реНрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЖрд╡реЗрджрди рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред




kari::curryN(F&& f, Args&&... args)


рд╣рдо рдЬрд┐рд╕ рддрд░реНрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЙрд╕рдХреА рд╕рдЯреАрдХ рд╕рдВрдЦреНрдпрд╛ N рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдХреЗ рддрд░реНрдХреЛрдВ рдХреА рдЪрд░ рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рдХрд░реА рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ ( args рдореЗрдВ рджрд┐рдП рдЧрдП рдХреЛ рдЫреЛрдбрд╝рдХрд░)ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


 char buffer[256] = {'\0'}; auto c = kari::curryN<3>(std::snprintf, buffer, 256, "%d + %d = %d"); c(37, 5, 42); std::cout << buffer << std::endl; // output: 37 + 5 = 42 

рдпрджрд┐ f рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдпрд╣ рдПрди рдХреЙрдкреА рдХреЗ рд▓рд┐рдП рдмрджрд▓ рджрд┐рдП рдЧрдП рдкреНрд░рдХрд╛рд░ рдХреЗ рдЖрд╡реЗрджрди рдХреЗ рд╕рд╛рде рдЕрдкрдиреА рдХреЙрдкреА рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИред




kari::is_curried<F>, kari::is_curried_v<F>


рдЬрд╛рдБрдЪ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕рд╣рд╛рдпрдХ рд╕рдВрд░рдЪрдирд╛рдПрдБ рдпрджрд┐ рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


 const auto l = [](int v1, int v2){ return v1 + v2; }; const auto c = curry(l); // output: is `l` curried? no std::cout << "is `l` curried? " << (is_curried<decltype(l)>::value ? "yes" : "no") << std::endl; // output: is `c` curried? yes std::cout << "is `c` curried? " << (is_curried_v<decltype(c)> ? "yes" : "no") << std::endl; 



kari::curry_t::operator()(As&&... as)


рдПрдХ рдХрд░реА рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкреВрд░реНрдг рдпрд╛ рдЖрдВрд╢рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рд╡рд╛рд▓рд╛ рдСрдкрд░реЗрдЯрд░ред рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдлрд╝рдВрдХреНрд╢рди F рдХреЗ рд╢реЗрд╖ рддрд░реНрдХреЛрдВ рдХреА рдХрд░реА рдлрд╝рдВрдХреНрд╢рди, рдпрд╛ рдкреБрд░рд╛рдиреЗ рддрд░реНрдХреЛрдВ рдФрд░ рдирдП рддрд░реНрдХреЛрдВ рдХреЗ рдмреИрдХрд▓реЙрдЧ рдкрд░ рдЗрд╕рдХреЗ рдЖрд╡реЗрджрди рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╛рдкреНрдд рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдореВрд▓реНрдп рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


 int foo(int v1, int v2, int v3, int v4) { return v1 + v2 + v3 + v4; } auto c0 = kari::curry(foo); auto c1 = c0(15, 20); // partial application auto rr = c1(2, 5); // function call - foo(15,20,2,5) std::cout << rr << std::endl; // output: 42 

рдпрджрд┐ рдЖрдк curryV рдпрд╛ curryN рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП curryV рдХрд┐рд╕реА рддрд░реНрдХ рдХреЗ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ рдХрд┐ рдХреНрдпрд╛ рдкрд░реНрдпрд╛рдкреНрдд рддрд░реНрдХ рд╣реИрдВред рдЕрдиреНрдпрдерд╛, рдпрд╣ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдлрд╝рдВрдХреНрд╢рди рд▓реМрдЯрд╛рдПрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


 auto c0 = kari::curryV(std::printf, "%d + %d = %d"); auto c1 = c0(37, 5); auto c2 = c1(42); // force call variadic function std::printf c2(); // output: 37 + 5 = 42 

рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рд╡рд┐рд╡рд░рдг


рдЬрдм рдЖрдк рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рд╡рд┐рд╡рд░рдг рджреЗрддреЗ рд╣реИрдВ, рддреЛ рдореИрдВ рд▓реЗрдЦ рдХрд╛ рдкрд╛рда рдЫреЛрдЯрд╛ рд░рдЦрдиреЗ рдФрд░ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдФрд░ рдвреЗрд░ рдХрд┐рдП рдЧрдП SFINAE рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП C ++ 17 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ, рд╕рд╛рде рд╣реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдореБрдЭреЗ C ++ рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред 14 рдорд╛рдирдХред рдЗрди рд╕рднреА рдХреЛ рдЖрдк рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдБ рдЖрдк рдЗрд╕реЗ рдЕрдкрдиреЗ рдкрд╕рдВрджреАрджрд╛ рдореЗрдВ рднреА рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ :)




make_curry(F&& f, std::tuple<Args...>&& args)


рдПрдХ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ curry_t рдмрдирд╛рддрд╛ рд╣реИ рдпрд╛ рджрд┐рдП рдЧрдП рдлрд╝рдВрдХреНрд╢рди f рдХреЛ рддрд░реНрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред


 template < std::size_t N, typename F, typename... Args > constexpr auto make_curry(F&& f, std::tuple<Args...>&& args) { if constexpr ( N == 0 && std::is_invocable_v<F, Args...> ) { return std::apply(std::forward<F>(f), std::move(args)); } else { return curry_t< N, std::decay_t<F>, Args... >(std::forward<F>(f), std::move(args)); } } template < std::size_t N, typename F > constexpr decltype(auto) make_curry(F&& f) { return make_curry<N>(std::forward<F>(f), std::make_tuple()); } 

рдЕрдм, рдЗрд╕ рд╕рдорд╛рд░реЛрд╣ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рджреЛ рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рддреЗрдВ рд╣реИрдВ:


  • рд╣рдо рдЗрд╕реЗ рдХреЗрд╡рд▓ рддрд░реНрдХреЛрдВ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ рдпрджрд┐ рдпрд╣ рдЗрди рддрд░реНрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛рдЙрдВрдЯрд░ N рд╢реВрдиреНрдп рдкрд░ рд╣реИ
  • рдпрджрд┐ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдирд╣реАрдВ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕ рдХреЙрд▓ рдХреЛ рдЖрдВрд╢рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ curry_t рд╣реИрдВ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдФрд░ рддрд░реНрдХ рдпреБрдХреНрдд рдлрд╝рдВрдХреНрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ curry_t рдмрдирд╛рддреЗ рд╣реИрдВ



struct curry_t


рдлрд╝рдВрдХреНрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рддрд░реНрдХреЛрдВ рдХреЗ рдмреИрдХрд▓реЙрдЧ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдЬрд┐рд╕реЗ рд╣рдо рдЗрд╕реЗ рдЕрдВрдд рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╕рдордп рдХрд╣реЗрдВрдЧреЗред рдпрд╣ рдСрдмреНрдЬреЗрдХреНрдЯ рд╡рд╣ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдХреЙрд▓ рдФрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред


 template < std::size_t N, typename F, typename... Args > struct curry_t { template < typename U > constexpr curry_t(U&& u, std::tuple<Args...>&& args) : f_(std::forward<U>(u)) , args_(std::move(args)) {} private: F f_; std::tuple<Args...> args_; }; 

рдРрд╕реЗ рдХрдИ рдХрд╛рд░рдг рд╣реИрдВ, args_ рдХрд╛рд░рдг рд╣рдо std :: tuple рдореЗрдВ рддрд░реНрдХ args_ рдХреЗ рдмреИрдХрд▓реЙрдЧ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВ:


1) рдПрд╕рдЯреАрдбреА рдХреЗ рд╕рд╛рде рд╕реНрдерд┐рддрд┐рдпрд╛рдБ :: рд░реЗрдлрд░реА рдХреЛ рд╕рдВрдЪрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕рдВрднрд╛рд▓рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдм рд╣рдореЗрдВ рдореВрд▓реНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ
2) рдЕрдкрдиреЗ рддрд░реНрдХреЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ ( std :: apply )
3) рдпрд╣ рд░реЗрдбреАрдореЗрдб рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдЗрд╕реЗ рдЦрд░реЛрдВрдЪ рд╕реЗ рдирд╣реАрдВ рд▓рд┐рдЦрдирд╛ рд╣реИ :)


рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдХреЙрд▓ рдХреА рдЧрдИ рд╡рд╕реНрддреБ рдФрд░ рдлрд╝рдВрдХреНрд╢рди f_ рдХреЛ рдЙрд╕рдХреЗ рдореВрд▓реНрдп рд╕реЗ рднреА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдПрдХ рдмрдирд╛рддреЗ рд╕рдордп рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╕рдордп рд╕рд╛рд╡рдзрд╛рди рд░рд╣реЗрдВ (рдореИрдВ рдиреАрдЪреЗ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ), рдпрд╛ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд╕рдВрджрд░реНрдн рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛, рдпрд╛ рдЗрд╕рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдирд╛ред рдирд┐рд░реНрдорд╛рддрд╛ред


рдПрдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ N рд╡реИрд░реЗрдбрд┐рдХ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХреЗ рд▓рд┐рдП рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛рдЙрдВрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред




curry_t::operator()(const As&...)


рдФрд░, рдЬрд╝рд╛рд╣рд┐рд░ рд╣реИ, рд╡рд╣ рдЪреАрдЬ рдЬреЛ рдЗрд╕реЗ рд╕рднреА рдХрд╛рдо рдХрд░рддреА рд╣реИ - рдСрдкрд░реЗрдЯрд░ рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред


 template < std::size_t N, typename F, typename... Args > struct curry_t { // 1 constexpr decltype(auto) operator()() && { return detail::make_curry<0>( std::move(f_), std::move(args_)); } // 2 template < typename A > constexpr decltype(auto) operator()(A&& a) && { return detail::make_curry<(N > 0 ? N - 1 : 0)>( std::move(f_), std::tuple_cat( std::move(args_), std::make_tuple(std::forward<A>(a)))); } // 3 template < typename A, typename... As > constexpr decltype(auto) operator()(A&& a, As&&... as) && { return std::move(*this)(std::forward<A>(a))(std::forward<As>(as)...); } // 4 template < typename... As > constexpr decltype(auto) operator()(As&&... as) const & { auto self_copy = *this; return std::move(self_copy)(std::forward<As>(as)...); } } 

рдХреЙрд▓рд┐рдВрдЧ рдСрдкрд░реЗрдЯрд░ рдХреЗ рдкрд╛рд╕ рдЪрд╛рд░ рдХрд╛рд░реНрдп рдУрд╡рд░рд▓реЛрдб рд╣реИрдВред


  1. рдПрдХ рдРрд╕рд╛ рдлрдВрдХреНрд╢рди рдЬрд┐рд╕рдореЗрдВ рдХреЛрдИ рдкреИрд░рд╛рдореАрдЯрд░ рдирд╣реАрдВ рд╣реИ рдЬреЛ рд╡реИрд░рд┐рдПрдбрд┐рдХ рдлрдВрдХреНрд╢рди ( curryV рдпрд╛ curryN рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдпрд╛ рдЧрдпрд╛) рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрд╣рд╛рдВ рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛рдЙрдВрдЯрд░ рдХреЛ рд╢реВрдиреНрдп рддрдХ рдШрдЯрд╛ рджреЗрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рд▓рд╛рдЧреВ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИ, рдФрд░ рдлрд┐рд░ рд╣рдо рд╡рд╣ рд╕рдм рдХреБрдЫ рджреЗрддреЗ рд╣реИрдВ рдЬреЛ рдЙрд╕рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдПред


  2. рдПрдХрд▓ рддрд░реНрдХ рдХрд╛ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЬреЛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрд╛рдЙрдВрдЯрд░ рдХреЛ 1 рд╕реЗ args_ (рдпрджрд┐ рдпрд╣ рд╢реВрдиреНрдп рдкрд░ рдирд╣реАрдВ рд╣реИ) рдФрд░ рд╣рдорд╛рд░реЗ рдирдП рддрд░реНрдХ рдХреЛ рддрд░реНрдХ рдХреЗ рдмреИрдХрд▓реЙрдЧ рдореЗрдВ рдбрд╛рд▓рддрд╛ рд╣реИ args_ рдФрд░ рдпрд╣ рд╕рдм args_ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред


  3. рдПрдХ рдЪрд░ рд╕рдорд╛рд░реЛрд╣ рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рддрд░реНрдХреЛрдВ рдХреЗ рдЖрдВрд╢рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдЪрд╛рд▓ рд╣реИред рдпрд╣ рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ рдЙрдиреНрд╣реЗрдВ рдПрдХ, рдПрдХ-рдПрдХ рдХрд░рдХреЗ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИред рдЕрдм, рджреЛ рдХрд╛рд░рдг рд╣реИрдВ рдХрд┐ рд╡реЗ рд╕рднреА рдХреЛ рдПрдХ рдмрд╛рд░ рдореЗрдВ рд▓рд╛рдЧреВ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:


    • рдЖрд╡реЗрджрди рдХрд╛рдЙрдВрдЯрд░ рд╢реВрдиреНрдп рд╕реЗ рдиреАрдЪреЗ рдЙрддрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рдХреЛрдИ рддрд░реНрдХ рдирд╣реАрдВ рдмрдЪрд╛ рд╣реИ
    • рдлрд╝рдВрдХреНрд╢рди f_ рдХреЛ рдкрд╣рд▓реЗ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдПрдХ рдФрд░ рдХрд░реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕рднреА рдЕрдЧрд▓реЗ рддрд░реНрдХ рджрд┐рдП рдЬрд╛рдПрдВрдЧреЗ

  4. рдЕрдВрддрд┐рдо рдлрд╝рдВрдХреНрд╢рди curry_t рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЙрд▓ рдХрд░рдиреЗ рдФрд░ rvalue рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдмреАрдЪ рдПрдХ рдкреБрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред



рд░реЗрдл-рдпреЛрдЧреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЯреИрдЧ рдкреВрд░реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд▓рдЧрднрдЧ рдЬрд╛рджреБрдИ рдмрдирд╛рддреЗ рд╣реИрдВред рдЗрд╕реЗ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрдирдХреА рдорджрдж рд╕реЗ рд╣рдореЗрдВ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рд╡рд╕реНрддреБ рдХреЛ rvalue reference рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреБрд▓рд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рд╣рдо рдЕрдВрддрд┐рдо рдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди make_curry рдореЗрдВ рдХреЙрдкреА рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рддрд░реНрдХ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЕрдиреНрдпрдерд╛ рд╣рдореЗрдВ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдлрд┐рд░ рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддрд░реНрдХреЛрдВ рдХреЛ рдХреЙрдкреА рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рддрд░реНрдХ рдЕрднреА рднреА рд╣реИрдВред


рдмреЛрдирд╕


рдирд┐рд╖реНрдХрд░реНрд╖ рдкрд░ рдЖрдЧреЗ рдмрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВ рдЖрдкрдХреЛ рдХрд╛рд░реА рдЪреАрдиреА рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рдПрдХ рдЬреЛрдбрд╝реЗ рдХреЛ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬреЛ рдХрд┐ рдЙрдирдХреЗ рдкрд╛рд╕ kari.hpp рдореЗрдВ рд╣реИрдВ рдЬреЛ рдмреЛрдирд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдпреЛрдЧреНрдп рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред


рд╕рдВрдЪрд╛рд▓рдХ рдЦрдВрдб


рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣рд╛рд╕реНрдХреЗрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рдЪреБрдХреЗ рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдП рдЧрдП рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЗ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╡рд┐рд╡рд░рдг рджреЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рд╡рд╛рд▓реЗ рдСрдкрд░реЗрдЯрд░ рд╡рд░реНрдЧреЛрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рдВрд░рдЪрдирд╛ (*2) , рдПрдХрд▓-рддрд░реНрдХ рдлрд╝рдВрдХреНрд╢рди рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕ рддрд░реНрдХ рдХреЗ рдЧреБрдгрди рдХрд╛ рдкрд░рд┐рдгрд╛рдо 2 рд╕реЗ рд▓реМрдЯрд╛рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЬреЛ рдореИрдВ рдЪрд╛рд╣рддрд╛ рдерд╛ рд╡рд╣ рд╕реА ++ рдореЗрдВ рдРрд╕рд╛ рдХреБрдЫ рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдирд╛ рдерд╛ред рдЬрд▓реНрджреА рд╕реЗ рдирд╣реАрдВ рдХрд╣рд╛!


 using namespace kari::underscore; std::vector<int> v{1,2,3,4,5}; std::accumulate(v.begin(), v.end(), 0, _+_); // result: 15 std::transform(v.begin(), v.end(), v.begin(), _*2); // v = 2, 3, 6, 8, 10 std::transform(v.begin(), v.end(), v.begin(), -_); // v = -2,-3,-6,-8,-10 

рдХреНрд░рд┐рдпрд╛ рд░рдЪрдирд╛


рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЕрдЧрд░ рдореИрдВ рдПрдХ рд╕рдорд╛рд░реЛрд╣ рд░рдЪрдирд╛ рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдирд╣реАрдВ рдХреА рд╣реИ рддреЛ рдореИрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд┐рд░рд╛рд▓рд╛ рдирд╣реАрдВ рдмрдиреВрдВрдЧрд╛ред рд░рдЪрдирд╛ рд╕рдВрдЪрд╛рд▓рдХ рдХреЗ рд░реВрдк рдореЗрдВ рдореИрдВрдиреЗ рдореИрдереНрд╕ рдореЗрдВ рд░рдЪрдирд╛ рд╕рдВрдХреЗрдд рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╕рднреА рдкреНрд░рддреАрдХреЛрдВ рдХреЗ рдирд┐рдХрдЯрддрдо (рдХреЗ рд░реВрдк рдореЗрдВ) operator * рдЪреБрдирд╛ред рдореИрдВрдиреЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рддрд░реНрдХ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдгрд╛рдореА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдХрд┐рдпрд╛ред рддреЛ, рдореБрдЭреЗ рдпрд╣реА рдорд┐рд▓рд╛:


 using namespace kari::underscore; // 1 std::cout << (_*2) * (_+2) * 4 << std::endl; // output: 12 // 2 std::cout << 4 * (_*2) * (_+2) << std::endl; // output: 10 

  1. рдХрд╛рд░реНрдпреЛрдВ рдХреА рд╕рдВрд░рдЪрдирд╛ (*2) рдФрд░ (+2) 4 рд▓рд╛рдЧреВ рд╣реЛрддреА рд╣реИред (4 + 2) * 2 = 12
  2. рдлрд╝рдВрдХреНрд╢рди (*2) 4 рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рд╣рдо рдкрд░рд┐рдгрд╛рдо рдкрд░ (+2) рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВред (4 * 2 + 2) = 10

рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдЖрдк рдкреЙрдЗрдВрдЯрдлреНрд░реА рд╢реИрд▓реА рдореЗрдВ рдХрд╛рдлреА рдЬрдЯрд┐рд▓ рд░рдЪрдирд╛рдПрдБ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ , рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рд╣рд╛рд╕реНрдХреЗрд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд╣реА рдЗрдиреНрд╣реЗрдВ рд╕рдордЭ рдкрд╛рдПрдБрдЧреЗ :)


 // (. (+2)) (*2) $ 10 == 24 // haskell analog std::cout << (_*(_+2))(_*2) * 10 << std::endl; // output: 24 // ((+2) .) (*2) $ 10 == 22 // haskell analog std::cout << ((_+2)*_)(_*2) * 10 << std::endl; // output: 22 

рдирд┐рд╖реНрдХрд░реНрд╖


рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдерд╛ рдХрд┐ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдЗрди рддрдХрдиреАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА, рдореБрдЭреЗ рдЗрд╕рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрдЦрд┐рд░рдХрд╛рд░, рдореЗрд░рд╛ рд▓рдХреНрд╖реНрдп рдЦреБрдж рдХреЛ рд╕рд╛рдмрд┐рдд рдХрд░рдирд╛ рдФрд░ рдирдП рд╕реА ++ рдорд╛рдирдХ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рдерд╛ред рдХреНрдпрд╛ рдореИрдВ рдРрд╕рд╛ рдХрд░ рдкрд╛рдКрдВрдЧрд╛? рдФрд░ C ++ рд╣реЛрдЧрд╛? рдЦреИрд░, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ, рдЖрдкрдиреЗ рдЕрднреА рджреЗрдЦрд╛ рдХрд┐ рд╣рдо рджреЛрдиреЛрдВ рдиреЗ рдРрд╕рд╛ рдХрд┐рдпрд╛ рд╣реИред рдФрд░ рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрди рд╕рднреА рд▓реЛрдЧреЛрдВ рдХрд╛ рдЖрднрд╛рд░реА рд╣реВрдВ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдкреВрд░реА рдмрд╛рдд рдкрдврд╝реАред

Source: https://habr.com/ru/post/hi436488/


All Articles