Язык Си: реализация каррирования
Каррирование, это преобразование функции от многих аргументов в набор функций, каждая из которых является функцией от одного аргумента. Вот тут статья в Википедии.
Как вернуть функцию из другой функции на чистом Си мне уже ответили тут, но возможно ли подобным образом сделать каррирование?
Ответы (2 шт):
Пример каррирования суммы. Первая строчка самая трудная (читается по спирали).
int (*sum (int x)) (int y)
{
int sum1 (int y)
{
return x + y;
}
return sum1;
}
int main (void)
{
return sum (12) (13);
}
В Си++ такое уже сотворили в виде лямбда функции. Берётся один аргумент, и создаётся функциональный объект, который будет вычислять функцию от остальных аргументов.
int x = 7 ;
auto f = [ x ] ( int y ) { return x * y ; } ;
f - это лямбда замыкание, где переменная x фиксируется, а f может вычислять функции с остальным аргументом y.
В Си руками это лямбда замыкание можно сотворить самому. А каррирование это всего-лишь массив таких лямбд.
# include <stdio.h>
typedef struct szamok zamok ;
typedef int funt ( zamok * , int ) ;
struct szamok {
int x ;
funt * f ;
} ;
static int funmul ( zamok * z , int y ) {
return z -> x * y ;
}
void callfun ( zamok * z , int y ) {
printf ( "x = %d : " , z -> x ) ;
printf ( "y = %d : " , y ) ;
int r = z -> f ( z , y ) ;
printf ( "r = %d\n" , r ) ;
}
int main ( ) {
// создание массива с разными x
// и можно с разными функциями
zamok za [ 12 ] ;
for ( int i = 0 ; i < 12 ; ++ i )
za [ i ] = ( zamok ) { .x = i , .f = & funmul } ;
// --- где-то далеко вызовы
for ( int i = 0 ; i < 12 ; ++ i )
callfun ( & za [ i ] , i ) ;
}
проверка :
x = 0 : y = 0 : r = 0
x = 1 : y = 1 : r = 1
x = 2 : y = 2 : r = 4
x = 3 : y = 3 : r = 9
x = 4 : y = 4 : r = 16
x = 5 : y = 5 : r = 25
x = 6 : y = 6 : r = 36
x = 7 : y = 7 : r = 49
x = 8 : y = 8 : r = 64
x = 9 : y = 9 : r = 81
x = 10 : y = 10 : r = 100
x = 11 : y = 11 : r = 121