Closures in C and Scala

Deutsch

Are closures at all possible in C, without falling back to writing some interpreter in C and using that interpreted langauge?

Function pointers alone are far less than what is needed for closures. But they are one of the building blocks. It is quite hard to get the signature right, but a typedef proves to be useful.

The next issue is that C does not allow inner functions by default and that it is not possible to automatically include a context, which is essential for the concept of closures.

But it is surprisingly easy to overcome that issue:

The function is defined before the function within which it should be meant to be defined. It has an additional parameter for some „context“-struct, which can be used to include variables from that context.

struct closure;
typedef int (*fun_type)(const struct closure *context, const int param);

This struct includes the variables and a function pointer:

struct closure {
int x;
fun_type fun;
};

Now the function definition in languages that support closures still have to be provided in some way and this is done anonymously with some mechanism called lambda or so, within another function or method whose variables are implicitely included. In a way methods can be considered a special case of this, since they include access to attributes of the enclosing object. In C all functions are defined in the regular way, but this time the fun_type signature needs to be observed. References to enclosed variables need to be bound by explicitely putting them into the context:

int f(const struct closure *context, const int param) {
return (context->x) + param;
}

The second order function that returns the closure can now be defined. We only have to accept the C notation, but it is fully equivalent to closures, just a little bit more noise:

struct closure *adder(int x) {
struct closure *result = malloc(sizeof(struct closure));
result->x = x;
result->fun = f;
return result;
}

Off course memory management is always an issue to observe in C…

Now the whole thing can be used like this:

int main(int argc, char *argv[]) {
int retcode;
if (argc < 2) { usage(argv[0], "not enough parameters"); } int x = atoi(argv[1]); int y = atoi(argv[2]); struct closure *cl = adder(x); int i; for (i = 0; i < y; i++) { printf("cl(%d)=%d\n", i, cl->fun(cl, i));
}
}

The complete example can be found on github.

Off course the same is much shorter and more elegant in Scala:

object Closure {
def main(args : Array[String]) : Unit = {
val x : Int = args(0).toInt
val y : Int = args(1).toInt
val f : ((Int) => Int) = adder(x);
val arr = (1 to y).map(f)
println(arr.toString)
}

def adder(x : Int) : ((Int) => Int) = {
(y => x+y)
}
}

Even this can be found on
github.

Is there a way to achieve Closures in C describes numerous approaches to this issue.

Share Button

Beteilige dich an der Unterhaltung

13 Kommentare

    1. That is an interesting aspect.
      I have actually avoided them, due to the fact that they are compiler specific. But it is interesting and I might take a look and write about them in the future.

  1. This is not really a closure…
    you have to write: cl->fun(cl, i), to use it.
    and by using cl as the first parameter, you are just hiding the closure parameters in a structure… to be a closure, you need to be able to call it with:
    cl->fun(i)

    having closure means the programmer is able to create functions dynamically…

    but may be there is something I missed???

    1. I think that it is more beautiful if you do not need this prefix, but since you only use things that you actually have anyway, in one case implicitly and in the other case explicitly, I would see this as legitimate way to write it. It is the same, just the implicitness is cleaner, more beautiful and of course for practical purposes what we want. It compiles to something explicit, as we have in C.

  2. It is not a closure, because we could simply avoid all that extra code, and pass in the object we need, the beauty of closures is that the context is hidden from the caller
    for example: int context = myObj->getSomeContextValue();

    instead of : int context = myObj->getSomeContextValue(myObj);

    1. That is an interesting question, if you want to call it closure or not. I understand your argument.
      The important point is, that there is a reasonably easy way in C to do what closures do in other languages.
      Too clumsy to be used as standard programming style in C, but easy enough to try it and even use it where it really makes sense.
      And of course it helps understanding what closures do.

    2. Brian has a point, however, C was not designed to do what other languages do. The example here is a great way to mimic a closure-like behavior. The REAL question is, why would you need closure in C? Convenience? Habit from other languages? I think making your code depending upon an artifical created feature is probably not the best solution.

      1. I do not recommend to spend a huge overhead to use paradigms in C for which the language was not made. So if you like object oriented programming, you CAN do it in C, but you find better languages for that. Same with functional programming.

        But this example helps understanding what closures are and how they work.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*