Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!lll-winken!elroy.jpl.nasa.gov!sdd.hp.com!hplabs!hpda!hpwala!hpwadac!lupienj From: lupienj@hpwadac.hp.com (John Lupien) Newsgroups: comp.lang.functional Subject: Re: function composition in C Message-ID: <1764@hpwala.wal.hp.com> Date: 1 Mar 91 20:25:00 GMT References: <6873@munnari.oz.au> <6316@rex.cs.tulane.edu> Sender: netnews@hpwala.wal.hp.com Reply-To: lupienj@hpwadac.UUCP (John Lupien) Organization: Hewlett Packard, Waltham, Mass Lines: 107 In article <6316@rex.cs.tulane.edu> fs@caesar.cs.tulane.edu (Frank Silbermann) writes: >In article <6873@munnari.oz.au> aet@felix.ee.mu.OZ.AU (bert) writes: >> Does anyone know how to write a compose function in C, >> without writing a Scheme interpreter to do it in. >> A call should look something like this: >> (compose(sqr,cube)) (2) >> which would evaluate to 64. >Compose would input two functions, and return a _new_ function. >This is impossible to do _directly_ in C, >as all functions must created at compile time. >> Feel free to use pointers wherever they seem appropriate. >> (so the above call could look like: >> (*compose(&sqr,&cube)) (2) ) >I suggest you let `compose' take _three_ parameters, >the two functions and also the argument upon which the >result is to be applied, so the call would look like: >compose(&sqr,&cube, 2). This is OK, but the "compose" function should be able to take any number of function pointer arguments directly. >Alternatively, you could name a new _datatype_ `composition', >which is _implemented_ as a record of two function pointers >(comp.first and comp.second). To create compositions, >you could write a function `compose' that inputs two function pointers >and returns them embedded in a single record of type `composition'. >To apply compositions, you write a function `apply' that inputs >a composition X and an argument Y, and returns: *x.second(*x.first(Y)). This is the data-structure driven (and probably most portable) way to go about it. However, if you put the data argument first, any machine with a C compiler and library that supports "varargs(5)" (which is the "portable" variable number of arguments support package) can be used to write a "compose" function that takes a data value (of fixed type), iteratively apply each of a list of function pointers to it, and return the result. Here's an example for "double" data. The argument list must be terminated with a null pointer in this implementation, but an integer count of functions to be applied could be supplied as the second argument instead. /* start of file dbl_compose.c */ #include #include double dbl_compose(); double sqare(); double cub(); double halve(); void main() { double foo; foo = dbl_compose(2.0, sqare, cub, halve, (double (*)())NULL); printf("result is %f\n",foo); } double dbl_compose(va_alist) va_dcl /* note lack of semi-colon */ { va_list ap; /* arg list scanner */ double result; double (*func)(); /* function pointer */ va_start(ap); /* initialize the arglist scanner */ result = va_arg(ap,double); /* read off the data arg */ while(1) { func = (double (*)())(void *)va_arg(ap,char *); if (func == ((double (*)())NULL)) { break; } result = (*func)(result); } va_end(ap); return(result); } double sqare(foo) double foo; { return(foo * foo); } double cub(foo) double foo; { return(foo * foo * foo); } double halve(foo) double foo; { return(foo/2); } /* end of file dbl_compose.c */ --- John R. Lupien lupienj@hpwarq.hp.com