[comp.lang.misc] final compose in C challenge

quale@picard.cs.wisc.edu (Douglas E. Quale) (01/30/91)

I think that the whole "can you write the procedure compose in C?" thread
has been confused by several unstated assumptions.  This is an attempt
to make the problem crystal clear.

Compose is a very simple procedure in SML.  The definition I used is
preceded by the '-' prompt, the compiler echos the inferred type on
the next line.

- fun compose(f,g) = fn x => f(g x);
val compose = fn : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b

Compose will work for ANY unary procedures f and g as long as the result
type of g is compatible with the input type of f.  The SML compiler will
detect any type clashes when compose is used.

As C doesn't have type variables (the 'a etc. above), a polymorphic
compose is probably too much to ask for.  (void *, C's only support
for generics, is rather weak.)

We'll make the problem much simpler by restricting f and g to be
functions from integers to integers.

- fun int_compose (f : int -> int, g : int -> int) = fn x => f(g x);
val int_compose = fn : (int -> int) * (int -> int) -> int -> int

Again, int_compose can be used anywhere that an int -> int procedure is
permitted.  The C equivalent is for compose to have the prototype

int (*compose)(int (*f)(int, int), int (*g)(int, int));

(I hope I got that right.)
Such a procedure (or function, using standard C terminology) could be used
anywhere that an int to int function could.  Making compose return
struct bletch DOESN'T do the job.  Every procedure taking procedure
arguments has to be rewritten.  If functions are first-class objects in
C, why do they need struct bletches to stand in for them?

This is a simple code or no question.  Either someone will fill in the
blank for me

int (*compose)(int (*f)(int, int), int (*g)(int, int))
{
	__________
}

or it can't be done.

-- Doug Quale
quale@picard.cs.wisc.edu