3 ms·
From Objective-C, you can make switch statements support strings with 6 lines of macro: ifndef TTD_SWITCH_STRING #define TTD_SWITCH_STRING #define TTD_CA
by AJRF 8y ago
From Objective-C, you can make switch statements support strings with 6 lines of macro:
ifndef TTD_SWITCH_STRING
#define TTD_SWITCH_STRING
#define TTD_CASE(str) if ([__s__ isEqualToString:(str)])
#define TTD_SWITCH(s) for (NSString *__s__ = (s); ; )
#define TTD_DEFAULT
#endif
- AnaniasAnanas 8y agoThis is quite cool, that being said, you would need to add a break at least at the end to that, unlike a regular switch. Plus it would not work in the case that you want multiple strings to lead to the same code
- burfog 8y agoSomebody, please just fix the language. Extend all the free compilers or, better yet, run the changes through the standards committee. People have been dying for this feature for over half a century. While you're at it, just make the feature generic. Handle arbitrary arrays, structs, unions, and floating-point types. The ... feature supported by gcc is also a huge usability improvement. Don't allow weird sorting order issues with strings. Don't allow it for structs and unions.
- unwind 8y agoNone of those types can be compared directly in C, so that's not making the feature "generic", it's making it magically super-powered. Associating comparison intelligence with arbitrary types is not very obvious how to do in C, but I guess the new super-switch could accept a function pointer in addition to the data, or something. Like: const char * s const = "bar"; switch (s, strcmp) { case "foo": printf("I got foo\n"); break; case "bar": printf("nopes, I got bar\n"); break; default: printf("neither foo nor bar :/\n"); } Which would be fine/acceptable, but not exactly how C tends to roll.
- glouwbug 8y agoWhy not just use an enum for the switch, and if strings need to reflect the enum, use an xmacro to expand the enum into an array of strings? https://github.com/glouw/andvaranaut/blob/master/src/Theme.c https://github.com/glouw/andvaranaut/blob/master/src/Theme.c
- burfog 8y agoThat doesn't seem to have anything to do with the problem. The problem: You have a string. (pointer to char with NUL termination) Depending on what that string is, you want to run different code. You want to do this with high performance and a minimum of fuss. No, it isn't an option to say "but what if I used an enum instead?". You have a string. A string is what you have. Currently in C, you must choose between high performance and a minimum of fuss. Pick one. The high-performance solution is to use bsearch or a perfect hash, mapping the string to an index of some sort. With purely standard C you would then use a normal switch. Using gcc extensions, you could get slightly better performance with a computed goto. Writing and maintaining this code is a pain, so most people don't bother. The minimum-fuss solution is a whole bunch of "else if ... else if ... else if ..." that tries each possibility in turn. The performance is terrible, but good enough for stuff like command line option parsing.
- burfog 8y agoNo, that entirely loses the expected performance and clarity of a switch. Remember that "arbitrary types" in C are not so exotic. A simple byte-by-byte comparison will do, skipping over any struct padding. Compilers today will generate code that uses various strategies (tree, hash, etc.) to do the comparisons, and it would be awful to impede that via an arbitrary user-specified comparison function. Doing a linear scan of every case, O(n*m) for the number of cases and the lengths of the strings, defeats the whole point of using a switch. One can already do that with cascading "if". For strings, the simplest syntax is to have the new behavior triggered by passing a pointer to any type which can be evaluated as an integer. That last requirement makes scanning for a terminator work in an obvious way. This does seem to lose the possibility of comparing arrays that are not NUL terminated, but that isn't the use case that people are dying for. Since the vast majority of the desire to switch on strings is involving ASCII keywords, it would be reasonable to prohibit gcc-style ranges (like "case 1 ... 4:") for non-ASCII strings. This means that the strings can be treated like giant integers stored in big-endian form. (after the NUL, treat it as more NUL going on forever) Clearly it is well-understood how to switch on integer values, and thus we can switch on strings. Right now the ways to switch on strings are terrible. If they are short, they can be memcpy into long long. With gcc one can use the computed goto extension, plucking values out of a table via bsearch or via a perfect hash function generated by something like gperf. It's all really miserable, leading low-performance programmers to just use cascading "if".