Last active
August 29, 2015 14:01
-
-
Save interstateone/6e47fa0dfc210388b2db to your computer and use it in GitHub Desktop.
A little demo of partial application for variadic blocks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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