logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

Spooky-code-at-a-distance.md (3172B)


  1. ---
  2. title: Spooky action at a distance
  3. date: 2021-01-19
  4. outputs: [html, gemtext]
  5. ---
  6. Einstein famously characterized the strangeness of quantum mechanics as "spooky
  7. action at a distance", which, if I had to pick one phrase about physics to be my
  8. favorite, would be a strong contender. I like to relate this to programming
  9. language design: there are some language features which are similarly spooky.
  10. Perhaps the most infamous of these is operator overloading. Consider the
  11. following:
  12. ```
  13. x + y
  14. ```
  15. If this were written in C, without knowing anything other than the fact that
  16. this code compiles correctly, I can tell you that x and y are numeric types, and
  17. the result is their sum. I can even make an educated guess about the CPU
  18. instructions which will be generated to perform this task. However, if this were
  19. a language with operator overloading... who knows? What if x and y are some kind
  20. of some Vector class? It could compile to this:
  21. ```
  22. Vector::operator_plus(x, y)
  23. ```
  24. The performance characteristics, consequences for debugging, and places to look
  25. for bugs are considerably different than the code would suggest on the surface.
  26. This function call is the "spooky action" — and the distance between the
  27. "+" operator and the definition of its behavior is the "distance".
  28. Also consider if x and y are strings: maybe "+" means concatenation?
  29. Concatenation often means allocation, which is a pretty important side-effect to
  30. consider. Are you going to thrash the garbage collector by doing this? *Is*
  31. there a garbage collector, or is this going to leak? Again, using C as an
  32. example, this case would be explicit:
  33. ```
  34. char *new = malloc(strlen(x) + strlen(y) + 1);
  35. strcpy(new, x);
  36. strcat(new, y);
  37. ```
  38. If the filename of the last file you had open in your text editor ended in
  39. `.rs`, you might be frothing at the mouth after reading this code. Strictly for
  40. the purpose of illustrating my point, however, consider that everything which
  41. happens here is explicit, opt-in to the writer, and obvious to the reader.
  42. That said, C doesn't get off scott-free in this article. Consider the
  43. following code:
  44. ```
  45. int x = 10, y = 20;
  46. int z = add(x, y);
  47. printf("%d + %d = %d\n", x, y, z);
  48. ```
  49. You may expect this to print out `10 + 20 = 30`, and you would be forgiven for
  50. your naivety.
  51. ```
  52. $ cc -o test test.c
  53. $ ./test
  54. 30 + 20 = 30
  55. ```
  56. The savvy reader may have already figured out the catch: add is not a function.
  57. ```
  58. #define add(x, y) x += y
  59. ```
  60. The spooky action is the mutation of x, and the distance is between the apparent
  61. "callsite" and the macro definition. This is spooky because it betrays the
  62. reader's expectations: it looks and smells like a function call, but it does
  63. something which breaks the contract of function calls. Some languages do this
  64. better, by giving macros an explicit syntax like `name!(args...)`, but,
  65. personally, I still don't like it.
  66. Language features like this are, like all others, a trade-off. But I'm of the
  67. opinion that this trade is unwise: you're wagering readability, predictability,
  68. debuggability, and more. These features are toxic to anyone seeking stable,
  69. robust code. They certainly have no place in systems programming.