Hacker News new | past | comments | ask | show | jobs | submit login

In case of just booleans, in C it's possible to use a "trick"/workaround with flags/bit operators. Although certainly more cumbersome and limited. E.g.:

  #define WIDTH 4
  #define MARGIN_LEFT 2
  #define MARGIN_RIGHT 1
  ...
  unsigned int flags =
    (width ? WIDTH : 0) |
    (margin_left ? MARGIN_LEFT : 0) |
    (margin_right ? MARGIN_RIGHT : 0);
  switch (flags) {
  case 0: //...
  case MARGIN_RIGHT: //...
  case MARGIN_LEFT: //...
  case WIDTH:                 // fallthrough
   case WIDTH | MARGIN_RIGHT: // fallthrough
   case WIDTH | MARGIN_LEFT:  // fallthrough
   case WIDTH | MARGIN_RIGHT | MARGIN_LEFT:
   //...
  case MARGIN_LEFT | MARGIN_RIGHT: //...
  }
Although you probably already knew it, and I totally admit it's much uglier and "workaround-ish". It's just that after reading "isn't powerful enough [...]" I felt a compulsory urge to show that It Can Be Done, and couldn't resist, sorry :)



Using a switch on an encoded value was my first thought too after seeing the pattern, and I think it's actually quite an elegant way of doing it - forming an array index from booleans and doing a table lookup with that. It's even clearer when the cases are ordered as

    (false, false, false) => { ... }  // 0
    (false, false, true ) => { ... }  // 1
    (false, true , false) => { ... }  // 2
    (false, true , true ) => { ... }  // 3
    (true , _    , _    ) => { ... }  // 4-7 (could be the default case)
Here's a possible small improvement that could, depending on the compiler, get rid of a few branches:

    #define WIDTH_BIT 2
    #define WIDTH (1<<WIDTH_BIT)
    #define MARGIN_LEFT_BIT 1
    #define MARGIN_LEFT (1<<MARGIN_LEFT_BIT)
    #define MARGIN_RIGHT_BIT 0
    #define MARGIN_RIGHT (1<<MARGIN_RIGHT_BIT)
    ...
    unsigned int flags = !!width << WIDTH_BIT
                       | !!margin_left << MARGIN_LEFT_BIT
                       | !!margin_right << MARGIN_RIGHT_BIT;
    ...

I'm not too familiar with Rust and Google isn't being helpful, so does anyone know how the Rust compiler implements pattern matching? Does it do something like the above or does it resort to if/else conversion?


Rust uses OCaml's algorithm for pattern matching, which is basically a dynamic programming algorithm that minimizes the number of branches. (It's really clever, worth reading about if you're bored.) The Rust compiler also contains heuristics to decide whether to use a jump table (LLVM switch statement) or not.


Is it 100% sure that !! gives only 0 or 1? I'd be very grateful for some hard citations/references for that (across various standards, C89/99/..., C++98/03/11...), I'd be happy to learn if I can safely rely on that?


C99: 6.5.3.3 p5: The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E).

C++11 (or a near enough draft): 5.3.1 p9: The operand of the logical negation operator ! is contextually converted to bool (Clause 4); its value is true if the converted operand is false and false otherwise. The type of the result is bool.

and 4.7 p4 on integral conversion: If the source type is bool, the value false is converted to zero and the value true is converted to one.

Both seem to suggest that when you apply !, you end up with something that is 0 or 1 when used as a number, and adding more ! won't get you out of that.


Thanks a lot! And still interested in earlier C/C++ standards, I'm much more likely to encounter them in the wild for long time.


Ah, sorry. Looks like C++03 has the same wording in the same sections as C++11, and ANSI C's Unary arithmetic operators section is numbered 3.3.3.3 and also has the same wording as C99.


Great, thanks!


I find that a lot easier to follow than the isolated 'true' and 'false' values in the rust code, especially considering that if you have any code at all in the body of such an 8 pronged switch the header will surely scroll out of view by the time you get to the bottom entries.


> Although you probably already knew it

No, I didn't. Clever! I love Hacker News sometimes :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: