5 ms·
This is a really cool story! Perhaps a slight segue, but I recently tried to learn CL for the first time and I was genuinely surprised by all the decades of ac
by troad 2y ago
This is a really cool story!
Perhaps a slight segue, but I recently tried to learn CL for the first time and I was genuinely surprised by all the decades of accumulated cruft (mainly masses of semi-redundant and soft-depreciated standard library functions, with bizarre names). The way people talk about Lisp, I'd expected something more elegant. I suppose I should try something like Scheme or Racket, but it's hard to find an introduction to those that isn't bone dry. (Recommendations welcome!)
I've also heard people say reading Lisp functions, inside out, ensconced (heya) in their parentheses, is somehow more comprehensible than sequential C style, but this state of enlightenment thus far eludes me. I can only speak for myself, but I definitely reason about code outside in rather than inside out.
- db48x 2y agoThe funny names all have history. They had history even at the time when Common Lisp was standardized.
- troad 2y agoNo doubt! I look forward to learning it in due course, but it's not exactly penetrable for a newcomer, particularly amidst a sea of parentheses.
- hickelpickle 2y agoLittle schemer is good, some people hate it some people love it. But it is a fairly light read the slowly teaches some syntax at a time, questions you about assumptions then revels the information as it goes on. It would be the least dry read. There is also sketchy scheme for a more thorough text, or even the rs7s standard, which are both pretty dry but short. What made me appreciate scheme was watching some of the SICP lectures (https://www.youtube.com/watch?v=2Op3QLzMgSY&list=PL8FE88AA54363BC46&index=1 https://www.youtube.com/watch?v=2Op3QLzMgSY&list=PL8FE88AA54...) and the little schemer to learn more. I also read some of the SICP along with it, though I put it down due to not having the time to work through it. Scheme is interesting and toying with recursion is fun, but the path a mentioned above is only really enjoyable if you are looking to toy around with CS concepts and recursion. You can do a lot more in modern scheme as well, and you can build anything out of CL. But learning the basics of scheme/lisp is can be pretty dry if you are just looking to build something right away like you already can in a traditional imperative language. But it is interesting if you are interested in a different perspective. But even RS7S scheme is still far from the batteries included you get with CL. I personal found the most enjoyment using Kawa scheme, which is jvm based and using it for scripting with java programs as it has great interop. I used it some for a game back end in the event system to be able to emit events while developing and script behaviors, I've also used it for configurations as well with a graphical terminal app, I used hooks into the ascii display/table libraries then kawa to configure the tables/outputs and how to format the data.
- troad 2y agoInteresting, thank you! I suppose what draws me to Lisp is that insight people say it gives them on programming. I already do much of my programming in functional style, so I'm trying to discover what it is about Lisp that's so beloved above and beyond that - I'm gathering it's a mix of recursion and the pleasantness of being able to get 'inside' the program, so to speak, with a REPL? I must also admit that I tend to run into a bit of a roadblock over Lisp's apparent view that programming is, or should be, or should look like, maths. I cut my teeth on assembly, so for me programming isn't maths, but giving instructions to silicon, where that silicon is only somewhat loosely based on maths. It tends to make me bounce off Lisp resources which by Chapter 2 are trying to show the advantages of Lisp by implementing some arcane algorithm with tail-end recursion.* But I'm very open to being persuaded I'm missing the bigger picture here, hence my ongoing effort to grok Lisp. (*Isn't tail-end recursion just an obfuscated goto?)
- Tevo 2y ago>recursion I think one of the reasons recursion is often emphasized in relation to Lisp is because one of Lisp's core data structures, the linked list, can be defined inductively, and thus lends itself well to transformations expressed recursively (since they follow the structure of the data to the letter). But recursion in itself isn't something particularly special. Though it is more general than loops, and so it is nice to have some grasp on it, and how looping and iteration relate to each other, and it is often easier to reason about a problem in terms of a base case and a recursive case rather than a loop, at a higher level you will usually come to find bare recursion mostly counterproductive. You want to abstract it out, such that you can then compose your data transformations out of higher level operations which you can pick and match at will, APL-style. Think reductions, onto which you build mappings and filters and groupings and scans and whichever odd transformations one could devise, at which point recursion isn't much more than an implementation detail. This is about collections, but anything inductive would follow a similar pattern. Most functional languages will edge you towards the latter, and I find Lisp won't particularly, unless you actively seek it out (though Clojure encourages it most explicitly, if you consider that a Lisp). >the pleasantness of being able to get 'inside' the program Indeed, that's one of the things makes Common Lisp in specific particularly great (and it is something other contemporary dialects seem to miss, to varying degrees). It lets you sit within your program and sculpt it from the inside, in a Smalltalk sort of way, and the whole language is designed towards that. Pervasive late-binding means redefining mostly anything takes effect pretty much immediately, not having to bother recompiling or reloading anything else depending on it. The object system specifies things such as class redefinitions and instance morphing and dependencies and so on, such that you can start with a simple class definition, then go on to to interactively add or remove slots, or play with the inheritance chain, and have all of the existing instances just do the right thing, most of the time. Many provided functions that let you poke and prod the state of your image don't make much sense outside of an interactive environment. There is a point to be made about abstraction, maths, and giving instructions to silicon (and metaprogramming!), but I'll have to pass for now. I apologize if this is too rambly, I tend to get verbose when tired.
- adonovan 2y ago> I'd expected something more elegant. Common Lisp is sort of the union of all dialects of Lisp, and some might say of all possible programming language paradigms. Scheme is more like the intersection of dialects, and is thus closer to the platonic ideal of Lisp. If you've never seen any dialect of Lisp before, Scheme may be a better introduction to the flavor as it's much easier to learn.
- kazinator 2y agoHow do you know the functions are "semi-redundant" and "soft-depreciated", if you've not worked in this before?
- troad 2y agoClever question, but a boring answer - the learning resource I was using simply said so (in fact, several did!). It seems common for learning resources to somewhat apologetically explain that Common Lisp has many functions with similar names but subtly different behaviours (e.g. (=) v (eq) v (eql) v (equal) v (equalp) v (string-equal)), before telling you which ones are in vogue.
- kazinator 2y agoThere is no "vogue" about it. Those functions test for different equalities. It's not the case that any of them are new versions of the others. (eq x y) tests whether x and y are the same object. It is very fast because typically all it has to do is do a machine word comparison, and that comparison is conclusive. (When it is false, there is no more work to do to rule out sameness.) If x and y are the same number, of the same type, it is not required to report true. Even if they are the the same number that you might think fits into a machine word, though on most implementations that situation will be eq. ANSI Lisp allows for implementations in which small, identical integer values like 7 are not necessarily eq. A Lisp implementation in which all numbers are "boxed" quantities on the heap could be conforming to ANSI. The eql function is like eq, but the same characters and same numbers of the same type are required to be equal under eql. For all other objects it is like eq. eql might be implemented in terms of doing an eq comparison, and then when that is false, doing more work to rule out sameness of numbers and characters. Common Lisp's hash tables can use different equalities; that is where it can make a bigger difference. Objects in an eq hash table can use a very simple, fast hashing function. Whereas objects in an eql hash table have to be hashed in such a way that equal integer or floating-point values have the same hash. A value that is a pointer to a boxed bignum integer has to be dereferenced to access some of the value bits of that object. There are some exotic functions in Lisp that you might never end up using, particularly in the list processing area like pairlis or revappend and whatnot.
- superdisk 2y agoAs someone else said, Scheme is the one that warrants the "pure, elegant" reputation. CL is full of crazy features and weird functions but it's because it's basically the continued lineage of the original Lisp from 1960. It can even run those old 60s vintage programs with minimal tweaks. https://web.archive.org/web/20150217111426/http://www.informatimago.com/develop/lisp/com/informatimago/small-cl-pgms/wang.html https://web.archive.org/web/20150217111426/http://www.inform... If you just want to play with macros and learn what makes the Lisp thing so special I'd recommend Clojure, it's like a stripped down CL with only functional features, and it's extremely nice and ergonomic.
- kqr 2y ago> I've also heard people say reading Lisp functions, inside out, ensconced (heya) in their parentheses, is somehow more comprehensible than sequential C style, but this state of enlightenment thus far eludes me. I can only speak for myself, but I definitely reason about code outside in rather than inside out. Based on my years tutoring university students in various programming languages throughout their courses, I suspect some of this is personal preference that's set before one starts programming. Some people who start with C-style languages find Lisp-style languages more intuitive, while some people who start with Lisp-style languages breathe a sigh of relief when they discover C-style languages. I haven't found any predictor of this ahead of time – as far as I can tell it's just something one discovers as one tries different languages.
- pjc50 2y agoAs I posted on the "cognition" lexer thread, some users prefer "left handed scissors". Just as it is not equally intuitive for everyone to write with a particular hand, it is not equally intuitive for everyone to program with a particular language.
- brabel 2y agoCL does have some weird stuff, after all it's coming from the 1960's LISP tradition. But after you get past some basic weird stuff, it's a quite wonderful language. > I can only speak for myself, but I definitely reason about code outside in rather than inside out. You can indent code to make it much easier to "parse", and use some macros that turn the code inside/out, it's more readable than most other languages. The CL cookbook is an excellent resource, and this page links to several other excellent resources and books you can read for free online: https://lispcookbook.github.io/cl-cookbook/ https://lispcookbook.github.io/cl-cookbook/ The "new docs" also present the documentation in a "modern" looking way (rather than the 90's looks of what you get if you Google around): https://lisp-docs.github.io/cl-language-reference/ https://lisp-docs.github.io/cl-language-reference/ About other Lisps... The Racket Guide is definitely not "bone-dry": https://docs.racket-lang.org/guide/intro.html https://docs.racket-lang.org/guide/intro.html It is well written and looks very beautiful to me. On another Scheme, I find Guile docs also great: https://www.gnu.org/software/guile/manual/html_node/index.html https://www.gnu.org/software/guile/manual/html_node/index.ht... They may be a bit more "dry" but they're to the point and very readable! In fact, I think Lisp languages tend to have great documentation. The guy who wrote is an excellent writer (he has written Racket books which are equally great) and I believe is the author of the Racket docs tool!
- Jach 2y agoHave you seen https://stevelosh.com/blog/2018/08/a-road-to-common-lisp/ https://stevelosh.com/blog/2018/08/a-road-to-common-lisp/ ? "Kludges" everywhere is applicable. On the other hand, having a function like "row-major-aref" that allows accessing any multi-dimensional array as if it were one dimensional is "sweeter than the honeycomb". I still think CL code can be beautiful. Norvig's in PAIP https://github.com/norvig/paip-lisp https://github.com/norvig/paip-lisp is nice. As for the inside-out remark, while technically you do it for even basic syntax, you don't always exactly have to, and it's very convenient to not do. Clojure has its semi-famous arrow macro that lets you write things in a more sequential style, it exists in CL too, and there's always the venerable let* binding. e.g. 3 options: (loop (print (eval (read)))) (-> (read) (eval) (print) (loop)) (loop (let* ((r (read)) (e (eval r))) (print e))) And even the first one isn't that bad to read. For the really annoying cases like a lot of arithmetic, just use the reader macro from the 90s that lets you write in infix mode rather than complain how the quadratic equation is harder to read in prefix notation.
- lispm 2y agoOn thing to keep in mind when you see the language, which evolved of several decades: it has low-level (go to, ...), mid-level (macros, ...) and high-level (CLOS + MOP) elements in one language. A reason for that: the low-level parts are code generation building blocks for the higher level parts. Example: The SERIES library (a higher-level way to think about loops and sequences) uses macros (mid-level) to transform code into efficient loops (-> low-level): https://github.com/rtoy/cl-series https://github.com/rtoy/cl-series So one reason for all this functionality is: the language is its own compilation target. One is not supposed to write all the code, but we can write code which writes the lower-level code.
- agumonkey 2y agoI'm part of the (lisp) crowd, I always had trouble and anger toward C, Java, (and even ADA for syntactic choices) and when I got into lisps it felt like finding home. There's less of what I don't like (side effects, syntax) and more of what I like (value oriented, composability, principled, interactive, tree/recursive thinking, ability to customize your language more). A 'cleaner' starting point might be clojure (lisp on top of the JVM). Rich Hickey tried to make it short and principled, leveraging interfaces for polymorphism. schemes are cool too. Some cruft in lisp I still like, like car/cdr .. in clojure they're named first/rest .. obviously more obvious.. yet a I miss using car and cdr to walk/deconstruct structures. There's something timeless about them.
- bmacho 2y ago> I suppose I should try something like Scheme or Racket, but it's hard to find an introduction to those that isn't bone dry. (Recommendations welcome!) Use it as a tool, instead of an end goal. Your end goal can be the SICP book, HtDP book, leetcode, pet project. Or literally whatever that you like doing.
- mark_l_watson 2y agoI kind of like the decades of accumulated cruft and I like that Common Lisp code I wrote decades ago still works as-is. More modern conveniences like Quicklisp make everything simple and a mellow experience to use. All that said, I also strongly recommend Racket. I just use a small part of the Racket ecosystem: compiler, REPL, Emacs bindings, and sometimes DrRacket. The library and packaging system is simple to get used to and use. Sorry for going off topic: I need to use Python a lot for my own research and projects, and I find Python tricky. Don’t ask me how often I blow away my Python installation, and occasionally even switch between project specific virtual environments and different miniconda environments. Yuck.
- hcarvalhoalves 2y agoThere's cruft, but there's also decades long backwards compatibility and feature completeness. Sitting down and doing actual work instead of fighting immature runtimes and toolchain isn't a bad idea, but unfortunately is something pervasive in this industry. In addition, nothing I've tried thus far comes even close to the experience of the CL debugger.