Higher order functions in C

后端 未结 8 1589
小鲜肉
小鲜肉 2020-12-05 19:31

Is there a \"proper\" way to implement higher order functions in C.

I\'m mostly curious about things like portability and syntax correctness here and if there are mo

相关标签:
8条回答
  • 2020-12-05 19:56

    In straight c, this is really only done through function pointers, which are both a pain and not meant for this type of thing (which is partially why they are a pain). Blocks (or closures, according to non-apple) are fantastic for this, though. They compile in gcc-4.x or something, and icc something, but regardless thats what you're looking for. Unfortunately, I can't seem to find any good tutorials online, but suffice to say it works something like this:

    void iterate(char *str, int count, (^block)(str *)){
      for(int i = 0; i < count; i++){
        block(list[i]);
      }
    }
    
    main() {
      char str[20];
      iterate(str, 20, ^(char c){
        printf("%c ", c);
      });
    
      int accum = 0;
      iterate(someList, 20, ^(char c){
        accum += c;
        iterate(str, 20, ^(char c){
          printf("%c ", c);
        });
      });
    }
    

    obviously this code is pointless, but it it prints each character of a string (str) with a space in between it, then adds all of the characters together into accum, and every time it does it prints out the list of characters again.

    Hope this helps. By the way, blocks are very visible in Mac OS X Snow Leopard api-s, and I believe are in the forthcoming C++0x standard, so they're not really that unusual.

    0 讨论(0)
  • 2020-12-05 19:57

    This is an answer to the question: how to compose functions in C, which is redirected here.

    You can create a data structure to implement a list data type. that structure can contain function pointers.

    #include<stdlib.h>
    #include<malloc.h>
    
    typedef (*fun)();
    
    typedef struct funList { fun car; struct funList *cdr;} *funList;
    
    const funList nil = NULL;
    
    int null(funList fs){ return nil==fs; }
    
    fun car(funList fs)
    {
       if(!null(fs)) return fs->car; 
       else 
       {
         fprintf(stderr,"error:can't car(nil) line:%d\n",__LINE__);
         exit(1);
       }
    }
    
    funList cdr(funList ls)
    { if(!null(ls)) return ls->cdr; 
      else 
      {
        fprintf(stderr,"error:can't cdr(nil) line:%d\n",__LINE__);
        exit(1);
      }
    }
    
    funList cons(fun f, funList fs)
    {  funList ls;
    
       ls=(funList) malloc(sizeof(struct funList));
       if(NULL==ls)
       {
         fprintf(stderr,"error:can't alloc mem for cons(...) line:%d\n",__LINE__);
         exit(1);
       }
    
       ls->car=f;
       ls->cdr=fs;
    
       return ls;
    }
    

    we can write a function comp which applies a list of functions:

    type_2 comp(funList fs, type_1 x)
    {  
       return (null(fs)) ? x : car(fs)(comp(cdr(fs),x)); 
    }
    

    An example of how it works. We use (f g h) as a short notation for cons(f,cons(g,cons(h,nil))), which is applied to a given argument x:

    comp((f g h),x)
    

    =

    f(comp((g h),x))
    

    =

    f(g(comp((h),x)))
    

    =

    f(g(h(comp(nil,x))))
    

    =

    f(g(h(x)))
    

    if you had used the polymorphic list type in a typed language like SML or Haskell the type of comp should be:

    comp :: ([a -> a],a) -> a
    

    because in that context all the members in a list have the same type. C can be more flexible in this sense. Maybe something like

    typedef void (*fun)();
    

    or

    typedef (*fun)();
    

    you should see what the C manual say about this. And be sure that all contiguous functions have compatible types.

    The functions to compose should be pure, i.e. without side effects nor free variables.

    0 讨论(0)
提交回复
热议问题