Skip to content

Instantly share code, notes, and snippets.

@JensAyton
Created April 28, 2014 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JensAyton/11385876 to your computer and use it in GitHub Desktop.
Save JensAyton/11385876 to your computer and use it in GitHub Desktop.
NSDictionaryOfVariableBindings at compile time, just because.
#import <Foundation/Foundation.h>
#define JADictionaryOfVariableBindings(...) \
[NSDictionary dictionaryWithObjects:(const id []){ __VA_ARGS__ } \
forKeys:(const NSString *[]){ JATEMPLATE_MAP(JATEMPLATE_NAME_FROM_ARG, __VA_ARGS__) } \
count:JATEMPLATE_ARGUMENT_COUNT(__VA_ARGS__)]
#define JATEMPLATE_NAME_FROM_ARG(ITEM) @#ITEM
/*
Evil macro magic.
JATEMPLATE_ARGUMENT_COUNT returns the number of elements in a __VA_ARGS__
list. Trivially modified from code by Laurent Deniau and
"arpad.goret...@gmail.com" (full name not available). Source:
https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/d-6Mj5Lko_s
This version relies on the GCC/Clang ##__VA_ARGS__ extension to handle
zero-length lists. It supports up to 62 arguments.
JATEMPLATE_MAP applies a unary macro or function to each element of a
parameter or initializer list. For example, "JATEMPLATE_MAP(foo, 1, 2, 3)"
is equivalent to "foo(1), foo(2), foo(3)".
*/
#define JATEMPLATE_ARGUMENT_COUNT(...) \
JATEMPLATE_ARGUMENT_COUNT_INNER(_0, ##__VA_ARGS__, JATEMPLATE_ARGUMENT_COUNT_63_VALUES())
#define JATEMPLATE_ARGUMENT_COUNT_INNER(...) \
JATEMPLATE_ARGUMENT_COUNT_EXTRACT_64TH_ARG(__VA_ARGS__)
#define JATEMPLATE_ARGUMENT_COUNT_EXTRACT_64TH_ARG( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define JATEMPLATE_ARGUMENT_COUNT_63_VALUES() \
62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#define JATEMPLATE_MAP(F, ...) \
JATEMPLATE_MAP_INNER(F, JATEMPLATE_ARGUMENT_COUNT(__VA_ARGS__), __VA_ARGS__)
#define JATEMPLATE_MAP_INNER(F, COUNTEXPR, ...) \
JATEMPLATE_MAP_INNER2(F, COUNTEXPR, __VA_ARGS__)
#define JATEMPLATE_MAP_INNER2(F, COUNT, ...) \
JATEMPLATE_MAP_INNER3(F, JATEMPLATE_MAP_IMPL_ ## COUNT, __VA_ARGS__)
#define JATEMPLATE_MAP_INNER3(F, IMPL, ...) \
IMPL(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_0(F, HEAD)
#define JATEMPLATE_MAP_IMPL_1(F, HEAD) F(HEAD)
#define JATEMPLATE_MAP_IMPL_2(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_1(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_3(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_2(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_4(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_3(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_5(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_4(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_6(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_5(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_7(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_6(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_8(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_7(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_9(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_8(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_10(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_9(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_11(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_10(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_12(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_11(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_13(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_12(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_14(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_13(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_15(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_14(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_16(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_15(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_17(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_16(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_18(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_17(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_19(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_18(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_20(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_19(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_21(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_20(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_22(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_21(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_23(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_22(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_24(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_23(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_25(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_24(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_26(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_25(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_27(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_26(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_28(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_27(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_29(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_28(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_30(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_29(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_31(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_30(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_32(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_31(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_33(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_32(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_34(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_33(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_35(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_34(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_36(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_35(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_37(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_36(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_38(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_37(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_39(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_38(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_40(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_39(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_41(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_40(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_42(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_41(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_43(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_42(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_44(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_43(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_45(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_44(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_46(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_45(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_47(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_46(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_48(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_47(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_49(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_48(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_50(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_49(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_51(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_50(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_52(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_51(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_53(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_52(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_54(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_53(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_55(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_54(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_56(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_55(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_57(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_56(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_58(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_57(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_59(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_58(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_60(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_59(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_61(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_60(F, __VA_ARGS__)
#define JATEMPLATE_MAP_IMPL_62(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_61(F, __VA_ARGS__)
@JensAyton
Copy link
Author

Example:

NSString *foo = @"Hello, World!";
NSNumber *bar = @42;

NSLog(@"%@", JADictionaryOfVariableBindings(foo, bar));

After preprocessing, this becomes:

NSString *foo = @"Hello, World!";
NSNumber *bar = @42;

NSLog(@"%@", [NSDictionary dictionaryWithObjects:(const id []){ foo, bar } forKeys:(const NSString *[]){ @"foo", @"bar" } count:2]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment