I'm trying to implement a version of Haskell's foldr function in C but have hit a wall making it generic as I want to make the + or * characters (char y in foldr) work as addition or multiplication. I was thinking of trying a macro but wasn't sure what would work.
Here the code:
int
foldr(int *v, int (*f)(int*), int x, char y)
{
int temp;
if(*v == (int) NULL) //v is null terminated int array
return x;
else{
temp = *v;
return temp y ((*f)(++v));
}
}
Main issue is making char y work so I can say:
int
sum(int *v)
{
return foldr(v, (sum), 0, '+');
}
and it would just work.
Thanks
I'll show a recursion-based approach. As an exercise, you could turn it into an iterative solution, if you wish.
(Warning: untested)
Haskell:
foldr :: (Int->Int->Int) -> Int -> [Int] -> Int
foldr f x [] = x -- base case
foldr f x (v:vs) = f v (foldr f x vs) -- recursion
C:
int foldr(int (*f)(int,int),
int x,
int *v, size_t length) {
// base case
if (length == 0) return x;
// recursion
return f(*v, foldr(f, x, v+1, length-1));
}
Test:
int add(int a, int b) {
return a+b;
}
int main() {
int a[] = {1,2,3} ;
int res = foldr(add, 0, a, sizeof a/sizeof *a);
printf("%d\n", res);
return 0;
}
If you pass a proper function pointer (like add) above, there is not need to pass the character operator '+'.
Note that functional programming languages also allow to build closures, as in:
let y = 5
in foldr (\x c -> x*y+c) 0 [1..3]
Note how the function \x c -> x*y+c also depends on the value of y. C does not allow to do craft closures, but you can emulate the captured y, if you allow an addition void * argument to the C function.
int foldr(int (*f)(void *, int, int),
void *data,
int x,
int *v, size_t length) {
// base case
if (length == 0) return x;
// recursion
return f(data, *v, foldr(f, data, x, v+1, length-1));
}
Test:
int g(void *data, int x, int c) {
int y = *(int *)data;
return x*y+c;
}
int main() {
int a[] = {1,2,3} ;
int y = 5;
int res = foldr(g, &y, 0, a, sizeof a/sizeof *a);
printf("%d\n", res);
return 0;
}
In this way you can reuse g with different values of y. If you need to capture more variables, pass a pointer to a suitable struct containing all such variables.
Related
I'm a bit confused as to how to implement the following. I want to have a function, func2, return a function that with call func1 with the specified parameters:
int func1(int x, int y, int z, int type){
// Calculations
}
int ((*func2)(int x, int y, int z))(int type){
// Return a pointer to func1 that with get x, y, z as parameters
// when called later, with type = type being fixed
}
Use:
my_func = func2(3);
printf("result = %d\n", my_func(1,2,3));
For this to work you need something called a closure which is basically a record with the function and the type as fields. Below is an example to illustrate the idea. In a real program you also need to check that malloc doesn't return NULL, and free the memory.
#include <stdio.h>
#include <stdlib.h>
typedef struct ClosureDesc *Closure;
struct ClosureDesc {
int type;
int (*function)(Closure c, int x, int y, int z);
};
int func1(Closure c, int x, int y, int z)
{
return c->type;
}
Closure func2(int type)
{
Closure c;
c = malloc(sizeof *c);
c->type = type;
c->function = func1;
return c;
}
int main(void)
{
Closure my_func;
my_func = func2(3);
printf("result = %d\n", my_func->function(my_func, 1,2,3));
return 0;
}
Function pointers syntax is a bit confusing but you can make it easier typedefing the functions itself. Then you can use "normal" pointer syntax.
typedef int func(int,int,int);
int func1(int x, int y, int z){
// Calculations
return 1;
}
int func2(int x, int y, int z){
// Calculations
return 2;
}
int func3(int x, int y, int z){
// Calculations
return 3;
}
func *selectfunc(int type)
{
func *f = NULL;
switch(type)
{
case 1:
f = func1;
break;
case 2:
f = func2;
break;
case 3:
f = func3;
break;
}
return f;
}
int main(void)
{
int type = rand()%3;
printf("%d", selectfunc(type)(1,2,3));
}
or
func *fptr = selectfunc(2);
fptr(1,2,3);
Here’s what I think you’re going for:
int func1( int x, int y, int z )
{
...
}
/**
* func2 takes an integer parameter and returns a
* pointer to a function that takes 3 integer
* parameters and returns int
*/
int (*func2(int type))(int, int, int)
{
/**
* This example is based on what you wrote in your
* question. Regardless of how you actually select
* which function to return based on the input, the
* return statement will be the same.
*/
switch ( type )
{
case 3:
return func1;
break;
default:
break;
}
return NULL;
}
int main( void )
{
int (*my_func)(int, int, int);
...
my_func = func2( 3 );
if ( my_func )
printf( "result = %d\n", my_func( 1, 2, 3 ) );
...
}
If you write func2 such that it can never return NULL and you want your co-workers to throw things at you, you can dispense with the my_func variable and just write
printf( "result = %d\n", func2(3)(1, 2, 3));
I wouldn’t recommend it though, unless you like rude comments in code reviews.
i have a little question.
i'm studying C with devc++ (as start) and i have seen as argument function you can pass a function, this is ok but why?
for example u can write as argument:
void myfunc(void(*func)(int)){}
but if u simple call function with his name and argument it is not better?
like example:
void myfunction (){name of func to call(myargs); }
there's a difference?
it seems the same thing but with more simple and short code
edit:
i want only know
void map (int (*fun) (int),int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = fun(x[i]);
}
why u use this instead of:
void map (int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = nameoffunction(yourargument);
}
You can use a function pointer as a parameter if you want your function to do different things depending on what the user wants.
Here's a simple example:
#include <stdio.h>
int add(int x, int y)
{
return x + y;
}
int subtract(int x, int y)
{
return x - y;
}
int multiply(int x, int y)
{
return x * y;
}
int divide(int x, int y)
{
return x / y;
}
int operation(int x, int y, int (*func)(int, int))
{
printf(" x=%d, y=%d\n", x, y);
return func(x,y);
}
int main()
{
int x = 8, y = 4;
printf("x+y=%d\n", operation(x,y,add));
printf("x-y=%d\n", operation(x,y,subtract));
printf("x*y=%d\n", operation(x,y,multiply));
printf("x/y=%d\n", operation(x,y,divide));
return 0;
}
A very good example is the classic sorting function qsort. It's a library function, which means that you only have access to it's prototype. In order to make qsort general, you have to write your own compare function. A typical implementation looks like this for regular integers:
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
And then, if you have an array arr of integers you can sort it with qsort(arr, sizeof(arr), cmpfunc)
You might ask why this is not built in the qsort function? After all, it would be easy to make it work for both floats and integers. Yes, but imagine if you have an array of structs that look like this:
struct {
char *firstname;
char *lastname;
int age;
} persons[10];
How would you sort this? Well, that's not obvious. You might want all three. In that case, write three different compare functions.
i want only know
void map (int (*fun) (int),int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = fun(x[i]);
}
why u use this instead of:
void map (int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = nameoffunction(yourargument);
}
Let's answer the question with a question - what if you want to perform more than one type of mapping? What if you want to map both x2 and √x?
You could certainly do something like
void map( int x[], int l, int type )
{
for ( int i = 0; i < l; i++ )
{
if ( type == MAP_SQUARED )
x[i] = int_square( x );
else if ( type == MAP_ROOT )
x[i] = int_root( x );
...
}
}
which works, but is hard to read and cumbersome to maintain - every time you want to perform a new mapping, you have to add a new case to the map function.
Compare that to
void map( int x[], int l, int (*fun)(int) )
{
for ( int i = 0; i < l; i++ )
x[i] = fun( x[i] );
}
...
map( x, l, int_square );
map( y, l, int_root );
You don't have to hack the map function to get different mappings - you only have to pass the function that operates on the individual elements. If you want to perform a new mapping, all you have to do is write a new function - you don't have to edit the map function at all.
The C standard library uses this form of delegation in several places, including the qsort function (allowing you to sort arrays of any type in any order) and the signal function (allowing you to change how a program reacts to interrupts dynamically).
The following code returns the error: Expression must have pointer-to-object
type. somehow the problem lies in the way I reference the parameters A, B and out which each point to a 2D array. Any help would be much appreciated.
The goal is to multiply two arrays.
#include <stdio.h>
void matrixmul(const float *A, const float *B, int m, int n, int k, float *out)
{
float value = 0.0;
int x, y, z;
for (x = 0; x < k; x++) {
for (y = 0; y < m; y++) {
for (z = 0; z < n; z++) {
float product = A[y][z] * B[z][y];
value = value + product;
printf("%lf", value);
}
out[y][x] = value;
value = 0;
}
}
}
int main(void) {
float a[2][3] = {
{ 1.0,2.0,1.0 },
{ 3.0,4.0,1.0 }
};
float b[3][1] = {1, 2, 3};
float array[2][1];
matrixmul((float *) a, (float *) b, 2, 3, 1, (float *) array);
return 0;
}
Since A is declared as const float *A in the function, A[y][z] is an invalid term. A[y] evaluates to type const float. You can't use an array operator, [z], with a float.
The same problem occurs with B and out.
You can define the function as
void matrixmul(const float A[][3], const float B[][1], int m, int n, int k, float out[][1])
{
...
}
and call the function simply as:
matrixmul(a, b, 2, 3, 1, array);
C99/C11 support variable length arrays. Assuming you can use compiler that supports C99/C11, you can define the function as
void matrixmul(int arows, int acols, int bcols,
const float A[arows][acols],
const float B[acols][bcols],
float out[arows][bcols])
{
...
}
and call the function using
matrixmul(2, 3, 1, a, b, array);
The function does not know the dimensions of your array, so it does not know how to calculate the address of a value given the row and column. You can use a function's arguments to define the dimensions of your matrix, however. You will have to rearrange the arguments in your function such that the arguments specifying the dimensions appear before the array. Using your function, it might look something like this:
void matrixmul(int m, int n, int k, const float A[m][n], const float B[n][m], float out[m][k])
By the way, I haven't really read fully through the function, but is out[y][k] = value; supposed to be out[y][x] = value;?
Suppose I have a function:
void add(int a, int b , int c);
and I have an array which contains 3 integer values:
int L[] = {1,2,3};
Now I want to pass these values to add without writing add(L[0],L[1],L[2]).
I mean is there a way of creating a Single input from multiple inputs and passing it to the function which will treat that single input as multiple inputs ??.
You could try this
int L[] = {1,2,3};
add(L, 3);
where
void add(int *x, int length)
{
// use x[0], x[1], etc.
}
But I am not sure why you are having problem with your current approach.
Another option would probably be to encapsulate those three integers into a structure and pass the structure along.
If you mean something like Python
def foo(a, b, c):
return a + b + c
x = (1, 2, 3)
print(foo(*x)) # the '*' does the magic of calling foo with 1, 2, 3
then this is not possible in portable C.
What you can do is change the interface of foo to accept an array of arguments, e.g.
int sum(int *data, int n) {
int tot = 0;
for (int i=0; i<n; i++) {
tot += data[i];
}
return tot;
}
can call it with
int x[] = {10, 20, 30, 40};
int res = sum(x, 4);
If you cannot change the function definitions and you have many of them with the same signature what you can do is use function pointers to factor out the call:
int sum3(int a, int b, int c) {
return a+b+c;
}
int mul3(int a, int b, int c) {
return a*b*c;
}
int call_int_int3(int(*f)(int, int, int), int* args) {
return f(args[0], args[1], args[2]);
}
...
int data[] = {10, 20, 30};
int sum = call_int_int3(sum3, data);
int prod = call_int_int3(mul3, data);
but you will need a different wrapper for each distinct signature (number and type of arguments and type of return value).
I'm working on a simple library which operate on vectors.
It define a type of function that is regularly used:
typedef float (*vec_pair_fun) (float x, float y);
For ease-of-use reason, I want to create a sorting function that use a vec_pair_fun to compare each element of a vector.
At the moment, I'm doing this:
static vec_pair_fun sort_function;
// follow improvements suggested by #chux below
static int converted_sort_function(const void* a, const void* b){
//old code: return (int) qsort_function(*(float*)a,*(float*)b);
float f = sort_function(*(float*)a,*(float*)b);
return (f > 0.0f) - (f < 0.0f);
}
void vecx_sort(int x, float v[], vec_pair_fun func){
sort_function=func;
qsort(v,x,sizeof(float),converted_sort_function);
}
but I don't really like that workaround because it's not threadsafe as sort_function can be changed by another thread.
Any idea on how to improve this?
EDIT:
One way would be to sort the array myself.
Recoding qsort is really not what I planned to do, so I'm really open for suggestions
Q: Any idea on how to improve this?
A: Do not cast float result to int for compare.
Maybe not OP's main concern but (int) sort_function(*(float*)a,*(float*)b); is weak.
The FP point result could be -0.4 or 0.4, both of these convert to (int) 0.
The FP point result could be > INT_MAXand conversion to int is UB.
Suggest:
static int converted_sort_function(const void* a, const void* b){
float f = sort_function(*(float*)a,*(float*)b);
return (f > 0.0f) - (f < 0.0f);
}
As to your thread safe problem, consider qsort_s() which passes in a context pointer. qsort_s() is specified in C11 Annex K, so it may not exist in your compiler.
errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
int (*compar)(const void *x, const void *y, void *context),
void *context);
Following wikibooks 5th C implementation and Apple's implementation of a quicksort algorithm, I was able to create my function.
It appear to be quicker than the stdlib version, and it has no global/static variable.
// x: length of v
// v: array of float
// func: a function that takes two float as argument and return a float
void vecx_qsort(unsigned int x, float v[], vec_pair_fun cmpf)
{
float pivot,tmp;
unsigned int al,l,r,ar,cnt;
while (x>8)
{
cnt=0;
al=l=1; r=ar=x-1;
pivot=v[x/2];
v[x/2]=v[0];
v[0]=pivot;
while (1)
{
while ( l<=r && (tmp=cmpf(v[l],pivot))<=0.0f ) {
if(tmp==0.0f){
cnt=1;
vecx_swap(1,v+al,v+l); //swap vl & val
al++;
}
l++;
}
while ( l<=r && (tmp=cmpf(v[r],pivot))>=0.0f ) {
if(tmp==0.0f){
cnt=1;
vecx_swap(1,v+r,v+ar);//swap vr & var
ar--;
}
r--;
}
if(l>r)
break;
cnt=1;
vecx_swap(1,v+r,v+l);
l++; r--;
}
if(cnt==0 && x<=32) // no swap made => almost sorted small array => insertion sort
break;
// swap values equal to pivot to the center
cnt = (al<(l-al))?al:l-al;
vecx_swap(cnt,v,v+l-cnt); // swap of element before al
cnt = ((ar-r)<(x-ar-1))?ar-r:x-ar-1;
vecx_swap(cnt,v+l,v+x-cnt); // swap of element after ar
l=l-al; // size of "smaller element array"
r=ar-r; // size of "bigger element array"
// Recursion on the shorter side & loop (with new indexes) on the longer
if (l>r) {
vecx_qsort(r, v+x-r, cmpf);
x=l;
}
else {
vecx_qsort(l, v, cmpf);
v+=x-r;
x=r;
}
}
// insertion sort
for (r=1; r<x; r++)
{
pivot=v[r];
for(l=r; l>0 && cmpf(pivot,v[l-1])<0.0f; l--)
v[l]=v[l-1];
v[l]=pivot;
}
}