Skip to content

Instantly share code, notes, and snippets.

@interstateone
Last active August 29, 2015 14:01
Show Gist options
  • Save interstateone/6e47fa0dfc210388b2db to your computer and use it in GitHub Desktop.
Save interstateone/6e47fa0dfc210388b2db to your computer and use it in GitHub Desktop.
A little demo of partial application for variadic blocks
#import <Foundation/Foundation.h>
#define apply(block, a) (^{ \
switch (a.count) { \
case 1: return block(a[0], nil); \
case 2: return block(a[0], a[1], nil); \
case 3: return block(a[0], a[1], a[2], nil); \
case 4: return block(a[0], a[1], a[2], a[3], nil); \
case 5: return block(a[0], a[1], a[2], a[3], a[4], nil); \
case 6: return block(a[0], a[1], a[2], a[3], a[4], a[5], nil); \
case 7: return block(a[0], a[1], a[2], a[3], a[4], a[5], a[6], nil); \
case 8: return block(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], nil); \
case 9: return block(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], nil); \
case 10: return block(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], nil); \
case 11: return block(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], nil); \
\
case 0: \
default: return block(nil); \
} \
}())
typedef id (^VariadicBlock)(id, ...);
typedef NSNumber *(^NumberOperator)(NSNumber *, ...);
typedef NSString *(^StringOperator)(NSString *, ...);
int main(int argc, char *argv[]) {
@autoreleasepool {
VariadicBlock (^partial)(VariadicBlock, NSArray *) = ^VariadicBlock(VariadicBlock block, NSArray *arguments) {
return [^id(id argument, ...){
va_list ap;
NSMutableArray *allArguments = [arguments mutableCopy];
va_start(ap, argument);
while ([argument isKindOfClass:[NSObject class]]) {
[allArguments addObject:argument];
argument = va_arg(ap, id);
}
va_end(ap);
return apply(block, allArguments);
} copy];
};
NumberOperator sum = ^NSNumber *(NSNumber *number, ...) {
if (!number) return @0;
NSMutableArray *arguments = [NSMutableArray array];
va_list ap;
va_start(ap, number);
while ([number isKindOfClass:[NSNumber class]]) {
[arguments addObject:number];
number = va_arg(ap, NSNumber *);
}
va_end(ap);
NSNumber *sum = [arguments valueForKeyPath:@"@sum.integerValue"];
return sum;
};
StringOperator concatenate = ^NSString *(NSString *fragment, ...) {
if (!fragment) return @"";
NSMutableArray *arguments = [NSMutableArray array];
va_list ap;
va_start(ap, fragment);
while ([fragment isKindOfClass:[NSString class]]) {
[arguments addObject:fragment];
fragment = va_arg(ap, NSString *);
}
va_end(ap);
NSMutableString *concatenated = [NSMutableString string];
for (NSString *fragment in arguments) {
[concatenated appendString:fragment];
}
return concatenated;
};
NSLog(@"Sum (3): %@", sum(@1, @2));
NSLog(@"Partially applied sum (3): %@", partial(sum, @[ @1 ])(@2, nil));
NumberOperator sum3 = partial(sum, @[ @1, @2 ]);
NSLog(@"Partially applied sum (6): %@", sum3(@3, nil));
NSLog(@"Partially applied sum (10): %@", sum3(@3, @4, nil));
NSLog(@"Concatenate (abc): %@", concatenate(@"a", @"b", @"c", nil));
NSLog(@"Partially applied concatenate (abc): %@", partial(concatenate, @[@"a"])(@"b", @"c", nil));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment