6 ms·
(I hammered out that answer right before I had to run on stage. A couple other big items I forgot:) A proper numeric tower. Python has complex numbers, but t
by ken 8y ago
(I hammered out that answer right before I had to run on stage. A couple other big items I forgot:)
A proper numeric tower. Python has complex numbers, but they don't seem well integrated (why is math.cos(1+2j) a TypeError?). Fractions are frequently very useful, too, and Python has them, in a library, but "import fractions; fractions.Fraction(1,2)" is so much more verbose than "1/2" that nobody seems to ever use them.
Conditions! Lisp's debugger capabilities are amazing. And JWZ was right: sometimes you want to signal without throwing. Once you've used conditions, you'll have trouble going back to exceptions. They feel restrictive.
(I've come to accept that in a language with immutable data types, like Clojure, exceptions make sense. Exceptions feel out of place, though, in a language with mutability.)
Other big wins: keywords, multiple return values, FORMAT (printf on steroids), compile-time evaluation, a native compiler (and disassembler) with optional type declarations.
Lisp is unique among the languages I've used in that it has lots of features that seem designed to make writing large programs easier, and the features are all (for the most part) incredibly cohesive.
- chalst 8y agoConditions, yes. If you have multiple dispatch, then building/supporting a numeric tower is natural. In your other reply you pointed out macros. They are a mixed blessing, easily misused. Other languages have them but use them more sparingly and making it harder to overlook their special status, which leads to better "code smell" in my opinion. Do take a look at Julia. It has learned deeply from CL and innovated further.
- ken 8y agoI can imagine how multiple dispatch could make a numeric tower a little easier to implement, but the limitations I see in Python and other languages don't appear to stem from that. You can already take the math.cos of most types of numbers (int, float, even fractions.Fraction, ...) just fine, or add a complex and a Fraction. Python has long dealt with two types of strings, several types of numbers, etc., with the same interfaces. This isn't a difficult problem to solve with single dispatch. Macros are easily misused, true, but so can any language feature. I can go on r/programminghorror and see misuses of if-statements. It's the classic argument against macros, and I hear it a lot, but I can't say I've seen it happen. 25 years ago, conventional wisdom said that closures were too complex for the average programmer, and today they're a necessary part of virtually every language. Could we be reaching the point where syntactic abstraction is simply a concept that every programmer needs to be able to understand? I think "macros are easy to misuse" comes from viewing macros as an island. In some languages (like C), they are: they don't really integrate with any other part of the language. In Lisp, they're a relatively small feature that builds on the overall design of the language. Omitting macros would be like a periodic table with one box missing. It'd mean we get language expressions as native data types, and can manipulate them, and control the time of evaluation, but we just can't manipulate them at compile time.