

OK, my code snippets are Common Lisp. But note that none of them involve list/vector/set literals. I was thinking of []
for array indexing and {}
for code blocks.
As for infix macros, sure, that’s not hard to do, but it’s not built into the language and there being “plenty of libraries” is part of the problem: They’re all subtly different, none are standard, and I suspect most people don’t use them anyway. (Plus there’s fun little design issues like whether a*x + b
should parse the same as a * x + b
, and if it does, then how do you refer to a variable called a*x
from an infix environment?)
It doesn’t solve the main issue anyway. Take this snippet from the “infix” readme:
(def hypot (fn [x y] (infix sqrt(x ** 2 + y ** 2))))
It ends with a cluster of ))))
(reinforcing the “lots of parentheses” impression) and all of those parentheses mean something different: From the outside in, we have the end of a symbol definition (def ...)
, the end of a function (fn ...)
, the end of a macro invocation (infix ...)
, and the end of a function call sqrt(...)
. It definitely isn’t just “the same number [of parentheses] as any other language that uses parentheses to make function calls”.
Compare e.g. these versions written in Haskell:
hypot = \x y -> sqrt (x ** 2 + y ** 2)
… or Perl:
sub hypot($x, $y) { sqrt($x ** 2 + $y ** 2)}
… or if you want to separate the function and symbol definition parts:
*hypot = sub ($x, $y) { sqrt($x ** 2 + $y ** 2) };
I disagree with pretty much everything you write here, but especially this:
My Perl example uses “mainstream language” syntax. Apparently that doesn’t count because it’s Perl (scary! mental overhead! write only!), so here’s exactly the same thing in JavaScript:
function hypot(x, y) { return Math.sqrt(x ** 2 + y ** 2);}
… or
const hypot = function (x, y) { return Math.sqrt(x ** 2 + y ** 2);};
… or
const hypot = (x, y) => Math.sqrt(x ** 2 + y ** 2);
Note how none of these involve four layers of nested parentheses.