#include // the protocol of objects that can behave "like function" @protocol FunctionCapsule -(id)computeWith: (id)x; @end // a commodity for "encapsulating" double f(double) typedef double (*func_t)(double); @interface FunctionCaps : NSObject { func_t function; } +(id)capsuleFor: (func_t)f; -(id)initWithFunc: (func_t)f; @end @implementation FunctionCaps -(id)initWithFunc: (func_t)f { if ((self = [self init])) { function = f; } return self; } +(id)capsuleFor: (func_t)f { return [[[self alloc] initWithFunc: f] autorelease]; } -(id)computeWith: (id)x { return [NSNumber numberWithDouble: function([x doubleValue])]; } @end // the "functions" composer @interface FunctionComposer : NSObject { id funcA; id funcB; } +(id) createCompositeFunctionWith: (id)A and: (id)B; -(id) initComposing: (id)A with: (id)B; @end @implementation FunctionComposer +(id) createCompositeFunctionWith: (id)A and: (id)B { return [[[self alloc] initComposing: A with: B] autorelease]; } -(id) init { [self release]; @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"FunctionComposer: init with initComposing!" userInfo:nil]; return nil; } -(id) initComposing: (id)A with: (id)B { if ((self = [super init])) { if ( [A respondsToSelector: @selector(computeWith:)] && [B respondsToSelector: @selector(computeWith:)] ) { funcA = [A retain]; funcB = [B retain]; return self; } NSLog(@"FunctionComposer: cannot compose functions not responding to protocol FunctionCapsule!"); [self release]; } return nil; } -(id)computeWith: (id)x { return [funcA computeWith: [funcB computeWith: x]]; } -(void) dealloc { [funcA release]; [funcB release]; [super dealloc]; } @end // functions outside... double my_f(double x) { return x+1.0; } double my_g(double x) { return x*x; } int main() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; id funcf = [FunctionCaps capsuleFor: my_f]; id funcg = [FunctionCaps capsuleFor: my_g]; id composed = [FunctionComposer createCompositeFunctionWith: funcf and: funcg]; printf("g(2.0) = %lf\n", [[funcg computeWith: [NSNumber numberWithDouble: 2.0]] doubleValue]); printf("f(2.0) = %lf\n", [[funcf computeWith: [NSNumber numberWithDouble: 2.0]] doubleValue]); printf("f(g(2.0)) = %lf\n", [[composed computeWith: [NSNumber numberWithDouble: 2.0]] doubleValue]); [pool release]; return 0; }