2
typedef logs_t(*logs_t)(char *);

logs_t logs(char *s) {
    printf("%s", s);
    fflush(0);
    return &logs;
}

Error:

log.c:1:17: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
typedef logs_t(*logs_t)(char *);
                ^
log.c:1:9: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
typedef logs_t(*logs_t)(char *);
~~~~~~~ ^
log.c:1:15: fatal error: function cannot return function type 'int (char *)'
typedef logs_t(*logs_t)(char *);
              ^
2 warnings and 1 error generated.

What I want to achieve here is to chain the call to logs:

logs("a")("b");
exebook
  • 32,014
  • 33
  • 141
  • 226
  • Well, simply put - you can't. You could return a `struct` though... – Antti Haapala -- Слава Україні Feb 12 '18 at 15:19
  • @JulienLopez This is not currying. Currying is getting a function fixing an argument of another function. Here OP just want to get a fixed-point. – Jean-Baptiste Yunès Feb 12 '18 at 15:21
  • For any type `T` and function `T f(void);`, the expression `&f` will be of type `T (*)(void)`, which is not compatible with `T`, *regardless of `T`*. You could hack something that *might* work with some serious casting gymnastics, but it wouldn't allow for chained function calls as in your example. – John Bode Feb 12 '18 at 15:40

2 Answers2

4

You can't do such a recursive type definition in C. But mutual recursion is possible - you can chain by returning a struct that will contain pointer to the function as a member:

#include <stdio.h>

struct foo {
    struct foo (*logs)(char *);
};

struct foo logs(char *arg) {
    puts(arg);
    return (struct foo){ logs };
}

int main() {
    logs("foo").logs("bar");
}

However, this is hardly useful in your case; nor in any other general case, since the foo doesn't get passed in as this, so you'd just end up typing . instead of ;.

I could see it only useful in only those cases where the function wouldn't always return itself ;)

Perhaps you'd want to use variable arguments instead.

2

This won't give you arbitrary chaining, but assuming that you're writing the code manually, and not in auto-generated code, and thus probably won't chain calls beyond a certain point, you can do something like:

#include <stdio.h>

typedef void (*ftype10)(char *s);
typedef ftype10 (*ftype9)(char *s);
typedef ftype9 (*ftype8)(char *s);
typedef ftype8 (*ftype7)(char *s);
typedef ftype7 (*ftype6)(char *s);
typedef ftype6 (*ftype5)(char *s);
typedef ftype5 (*ftype4)(char *s);
typedef ftype4 (*ftype3)(char *s);
typedef ftype3 (*ftype2)(char *s);
typedef ftype2 (*ftype1)(char *s);
typedef ftype1 (*ftype)(char *s);

ftype logs(char *s) {
    printf("%s\n", s);
    fflush(0);
    return (ftype)&logs;
}

int main() {
    logs("line1")("line2")("line3");
    return 0;
}
Andru Luvisi
  • 24,367
  • 6
  • 53
  • 66