General map operation in C
Question: how can i define a general map operation on an array in C?

ideally I want something like python's map(function,array) ~~ but as a macro.
I believe this would be something like C++'s std::transform, but would be in
C, and not use iterators..

(this would be unary operation) I was thinking something like:

    
    
    template <class T*, class U*,size_t N>
    T* map(T (*func)(U), U* arr,size_t N)
    {
       T* tmp = (T*)malloc(sizeof(T) * N);
       size_t i;
       for(i=0;i<N;i++)
       {
           *(tmp+i) = *func(*(arr+i));
       }
    }
    

... but of course templates are in C++.. so how can I 1) do the latter and 2)
if you could, could you fix the above code snippet.

Thanks


Answer: For a template like this, there is a fairly straightforward translation to
macros; the major syntactic wrinkle is that you can't return the result array,
the variable to write it to has to be another parameter.

    
    
    #define map(func_, input_, output_, type_, n_) do { \
        output_ = xmalloc(sizeof(type_) * (n_));        \
        size_t i_;                                      \
        for (i_ = 0; i_ < (n_); i_++)                   \
            output_[i_] = func_(input_[i_]);            \
      } while (0)
    

This is not as type-unsafe as it looks, provided you pay attention to your
compiler warnings. However, it is _not_ particularly safe if any of the actual
arguments to a use of this macro isn't a simple identifier. Most importantly,
_catastrophic_ things will happen if any of the actual arguments has side
effects.

This can be cured, as can the inability to return the result array, but only
if you're willing to use GNU extensions...

    
    
    #define gnumap(func_, input_, type_, n_) ({                    \
        __typeof(func_)   func__   = (func_);                      \
        __typeof(input_)  input__  = (input_),                     \
                          output__ = xmalloc(sizeof(type_) * n__); \
        __typeof(n_)      n__      = (n_),                         \
                          i__;                                     \
        for (i__ = 0; i__ < n__; i__++)                            \
            output__[i__] = func__(input__[i__]);                  \
        /* return */ output__;                                     \
      })
    

Would I do either of these in real life? Probably not, but sometimes it really
is the least bad available option. Think of it as one step shy of rewriting
that critical inner loop in assembly language.

(`xmalloc`, in case you're unfamiliar with it, is the conventional name for a
user-written wrapper around `malloc` that either succeeds or crashes the
entire program. I use it here to dodge the question of how to cope with
`malloc` failing.)

