S-exps can be good for arithmetic too though.
S-expressions allow n-ary operators:
(+ (* 3 x y) (* a b z w) (* r s t u v))
There is a systematic way to break up large expressions across multiple lines, which helps readability. Infix doesn't have a satisfactory way to do this: (+ (* 3 x y)
(* a b z w)
(* r s t
u v))
We see just from from the + *
*
*
pattern that we have a sum of three products.S-exps are unambiguous. You never misread an arithmetic (or any other) S-exp due to precedence, unless it's a macro that has created precedence rules among its arguments (vanishingly rare).
N-ary math functions associate left to right in Common LIsp: (+ a b c d) means we add (a b) first, then c, and d. This makes a difference when you have mixed types, which have to undergo conversions, and when you have non-associative types like floating-point.
If I'm cribbing some numeric calculation to use in my code (whether that code is Lisp or not), and have examples in half a dozen languages, none of which I use, I will crib it from that one that is a Lisp dialect, just because of the vanishingly small opportunity for getting it wrong due to some ambiguity issue.
My reservation would be that most applications of arithmetic operators are binary and not ternary. A typical expression in one of my C programs at least has some function call, some subscript, some member access, some addition / subtraction / multiplication / division. But very few have more than one of each. Overall arithmetic is actually quite rare by itself in most code.
It's trivial for me to write x = (-b + sqrt(b^2 + 4 * a * c)) / (2 * a).
But writing (setf x (/ (+ (- b) (sqrt (+ (* 4 a c) (* b b)))) (* 2 a))).
That's a mind bender. Were this my source code, I'd probably put the (* 2 a) on the next line (properly indented) so it stood out as the divisor.
All that said, honestly, the physical task of writing Lisp code is just so much better than anything else. There's something satisfying closing up all of the parens. And I just love using-hyphens-for-identifiers vs CamelCase or using_underscores.
Should we consider Python's NumPy as not a feature of Python because it's not a built-in library?
A commenter says they prefer to write infix math. Lisp has a completely ordinary, stable, well-known, 30-year-old library to do it. Thus the commenter's concerns are largely allayed.
Not having it in the standard library means people have a choice to use it or not, and it also means one can't expect all Lisp code which has infix math to use it, but it certainly does not means the commenter will be perpetually hamstrung in reading and writing complicated math formulas.
Have people written bad, useless, nearly antagonistic macros? Sure, but that happens with any abstraction in any language, including humble functions.
Functions (at least in languages where they really are functions) are a lot safer; they're inherently compositional, and they follow the rules of the language. Most people have an intuition for what a macro should and shouldn't do, but there are very few guardrails that actually make that concrete, and often different team members will disagree about where the boundary between "sensible syntax sugar" and "inscrutable" lies.
I've brought the library up many times because CL, unlike so many other languages, really lets you extend it. Want a static type system? https://github.com/coalton-lang/coalton/ Want pattern matching? No need to wait for PEP 636, https://github.com/guicho271828/trivia/ If all that keeps someone from trying CL, or from enjoying it as much as they could because of some frustration or another, due to lacking <insert feature here> out of the box, chances are it is available through a library. (Or heck, even just tooling setup. Tab completion for symbols and jumping to function definitions are just two great things modern programmers enjoy in all sorts of languages, CL too, if someone doesn't have that setup I wonder if they must enjoy pain.)
#I( (-b + sqrt(b^^2 - 4*a*c))/(2*a) )
That is completely valid Lisp if you need it. In fact, you can change your editor to highlight #I(...) if you want it to stick out a little more since it's "different" than usual prefix notation.Suffice it to say, a binary expression like
(+ b (* m x))
probably doesn't warrant bringing in a library, but if you're calculating orbital dynamics of the solar system, then perhaps having the above library would be useful.And that's exactly how written math does it (big bar for division of complex terms). Infix code notation has an extra set of '() around the numerator and denominator which helps in this specific case.
I don't know how much of this is not being used to "dancing" but being entirely used to dealing trees of infix terms.
x = (-b + sqrt(b^2 + 4*a*c)) / (2*a)
is obviously conceptually clearer than (setf x (/ (+ (- b)
(sqrt (+ (* 4 a c)
(* b b))))
(* 2 a)))
i however think the latter is computationally clearer. also i think the difference is most striking when we use well known infix formulas such as the quadratic formula. you would not have this effect with the cubic equation for example - https://en.wikipedia.org/wiki/Cubic_equation#Cardano.27s_met...Is there utility assuming everyone who doesn't share your opinion is an Alien? I find it just causes the 103rd purple proboscis to itch. ;)