Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: I want to start learning Lisp. Where do I begin?
222 points by priyanshuraj on Dec 16, 2020 | hide | past | favorite | 204 comments
There are multiple versions of Lisp. Multiple compilers. What is a good one for someone new to pick?

I use VS Code and Vim. Are they suitable for learning Lisp?




Racket Scheme & SICP is a fun way to start playing, especially if you are into theoretical concepts of CS and programming, like higher order programming and abstraction.

The documentation for Racket is excellent, see e.g.

https://docs.racket-lang.org/quick/index.html

... and many people have created online resources to adapt SICP to Racket, as well as other learning texts. I like Beautiful Racket, e.g.

https://beautifulracket.com/explainer/lists.html

You can use #lang sicp and start playing around with the free online reformatted SICP text here:

http://sarabander.github.io/sicp/

I recommend getting a print copy of SICP, though, and working through the examples in a real DrRacket environment on your computer.

IMO, if you end up going deep in the "lispy" direction after playing with Racket, you'll probably be drawn to Clojure as it is the Lisp with the biggest "production use" community at the moment. So long as you can put up with some JVM warts, it, too, will be a good experience.


I have to second this. Racket is absolutely the best place to start. There are great books for beginners, and the documentation is top notch.

it comes with its own editor (Dr. Racket) that does some really helpful things for beginners, like hovering over a variable and seeing lines drawn to where it's being used.

It's not the fastest lisp, but that's ok. It's spectacular for learning and has a huge ecosystem too. My "daily driver" is Chicken Scheme, but i wouldn't recommend it to a beginner. The docs just aren't helpful to newbs (and frequently frustrating to me even though it has one of the better set of docs)

Vim is meh for Lisp & Scheme, and I'm a Vim fan. Emacs is great. If you're a Vim user check out Doom Emacs. It's great for us geeks who love vim but want more power and better lisp support. But... start with Dr. Racket for now.

Others have mentioned the SICP book, and it is good but i wouldn't suggest it as as "how to start with lisp" book. Also, watch the free lectures of the course from MIT. Very good, and make it way easier to work through the book.


I'm trying to make the neovim lisp world a little more pleasant with Conjure :) just for those that absolutely can not switch to emacs long term (like me)

https://github.com/Olical/conjure

It's written in a lisp, runs as lua and supports: Clojure, Fennel, Racket and Janet with a bunch more to come.


Vim is meh for Lisp & Scheme, and I'm a Vim fan. Emacs is great. If you're a Vim user check out Doom Emacs.

There is always spacemacs: https://www.spacemacs.org/


SICP is also a fantastic book because such a high percentage of all of the interview questions you'll be asked are represented there, but you end up really quite fundamentally understanding the solutions and I think that translates really well into the code people write in interviews.


I also recommend a milder version, a stepping stone, before jumping to SICP, Simply Scheme. The book is available online for free[0]

[0]:https://people.eecs.berkeley.edu/~bh/ssch1/showing.html


ClojureScript which targets JavaScript as the host language (https://clojurescript.org/) is a good option on the Clojure side.

ClojureScript is great if you're drawn towards the "production use" side as pixelmonkey said and already have knowledge of the Javascript / Node ecosystem.


I'd like to add that there's also a large Discord community for Lispers here: https://discord.gg/eHectVPqJ4


Can I read SICP while learning Clojure? Is lisp very different?


I wouldn't, unless you already know Scheme well. Otherwise, you're essentially learning two programming languages at once, and you won't know if your mistakes are because you misunderstand Scheme, Clojure, or both.


There are a few people who have translated the solutions to Clojure, this one looks like the most comprehensive: http://www.sicpdistilled.com/


It looks like only chapter 1 is completed. A lot of chapter 2, and the just bits of 3 and 4.


Not sure Clojure can do all the recursion stuff (TCO), which would be good to have in a language, when working through SICP exercises. I would not recommend it for SICP. Better start with a Scheme, to have the least amount of friction.


You can trivially use recur for self-recursion: call (recur x) instead of (my-fn x) inside your function.

(There's also trampoline for mutual recursion cases)


Is trampolining automatic, or does it have its own syntax as well?

Even a little thing like (recur ...) could be a tiny amount of friction. But good to read, that the usual cases are apparently handled well in the language.


The builtin helper function is called trampoline, it's a higher order function that relies on the mutually recursive functions returning "trampolines" or closures that do the desired subsequent call.

The trampoline pattern is an old trick that can also be imlemented in other languages to avoid stack consumption in mutually recursive calls.


I know what trampolining does, thank you.

That's unfortunate, that it is an additional function call, which needs to be explicitly written out. I'd guess such is necessary ultimately, because of limitations of the JVM and its limitations regarding recursion.


> Can I read SICP while learning Clojure? Is lisp very different?

Clojure is Lisp!!! with some nice out of the box semantics like immutability.


There are obviously many possible paths, so I can only really tell you what I've done. I can't say it's necessarily the best approach.

For me, I decided to start with Common Lisp. I installed SBCL, Slime for Emacs, and started working through the book Practical Common Lisp. By and large this seems to be a workable approach, but I will offer up this caveat. The PCL book is very much "project based" in that the author walks you through building a couple of actual applications. This is a Good Thing™ for the most part, but it does mean that you don't necessarily get things in the order you might expect.

There's a part of me that almost wishes I'd started with a book that takes more of an approach of "programming is ultimately sequence, selection and iteration. Here's how you do sequence in Lisp. Here's how you do selection. Here's how you do iteration. Now here's all the Fancy Lisp Stuff™".

The reason I say that, is because if you have at least the primitives for sequence, selection, and iteration (and maybe some I/O) in your mental toolbox, you can start building more or less arbitrary programs. With the PCL book structure you don't get to, for example, iteration, until moderately deep into the book. You do get there of course, but the early parts left me with an uneasy feeling like "geez, I don't even know how to write a loop in this language yet, when am I ever going to be able to just start coding in Lisp on my own?" if that makes sense.

Possibly one could complement PCL with another book, or online materials, but so far I've mostly just been grinding through PCL and haven't looked at any other Lisp books.

HTH.


I wouldn't focus too much on "sequencing, selection, and iteration". That's only the start of it. It's how you think if you're programming Python or Java or C or whatever.

With Lisp you can better think in terms of abstractions. In particular how do you do data abstraction, how do you do functional abstraction (that's the control flow: sequencing selection and iteration) and how do you do syntactic abstraction?

That last one is where Lisp (any Lisp) really comes into its own. It's where you go beyond the expressiveness of those other programming languages. Whether you go with defmacro or define-syntax, it opens up a whole other world.

And the expressiveness here isn't meant to suggest that you can write programs that you can't in other languages (they're all Turing complete) but that you can write new kinds of control flow and scoping constructs so you're not limited to the sequencing selection and iteration that the language provides.


And the expressiveness here isn't meant to suggest that you can write programs that you can't in other languages (they're all Turing complete) but that you can write new kinds of control flow and scoping constructs so you're not limited to the sequencing selection and iteration that the language provides.

That's all great... once you already know how to use the language. But, at least relative to the way I think and learn, I really want to quickly be able to do three or four things when learning a new language: sequence, selection, iteration, and console I/O. Once I can do that, I can write essentially any arbitrary program. And then I can start adding onto my knowledge and learning the more interesting ways of doing things.

Maybe I'd have a different perspective if I'd learned Lisp first, instead of having 20+ years of programming in Algol derived languages under my belt first. But I do feel uncomfortable spending days and weeks with a language and not even learning how do use (their version of) a for loop or whatever.


This is a bit off-topic, but something you said resonated with me.

> The PCL book is very much "project based" in that the author walks you through building a couple of actual applications. This is a Good Thing™ for the most part, but it does mean that you don't necessarily get things in the order you might expect. > > There's a part of me that almost wishes I'd started with a book that takes more of an approach of "programming is ultimately sequence, selection and iteration. Here's how you do sequence in Lisp. Here's how you do selection. Here's how you do iteration. Now here's all the Fancy Lisp Stuff™".

I feel like I'm in the minority in that I prefer to NOT learn things by just "diving in". I am much more successful when I start from the absolute fundamentals. There are objective pros and cons to either approach, but I suspect the success factor is based on one's personality (or some such).

If you start with the fundamentals, it's hard to know if you have any mastery until you try to do something "real". And then you might get frustrated because nobody taught you, e.g., how to do a network call in this programming language. It's also less rewarding because you can spend hours/days/weeks before actually "doing" anything.

If you start by diving in to a project, it's hard to know if you're doing things "the right way" or if you're just porting over bad habits from some other language you're familiar with. Sure, I got it to work, but is it good, or did I just cement in some bad habits?

The first time I drove a standard transmission car, I didn't stall it a single time. Because I read on the internet for a week about how car transmissions work and the difference between a manual and automatic gearbox. I do the same thing with programming languages. The first thing I want to know is what is the memory model approximately like (everything is a reference, values + references, are allocations cheap or expensive), what is the "philosophy" of the language (everything is an object, function composition is the blessed approach, mutability is bad, types are most/least important), etc. Then I want basic mechanisms: loops, iterators, lists or arrays, threads/futures/coroutines. Etc, etc.

That being said, SICP is kind of nice in that it finds an interesting middle ground where you're definitely learning details of the scheme language (applicative order vs normal order, recursion, etc) while it also feels like the details of the language is not the entire point.

No real point here. Just inspired by your comment and thought I'd share my own experience.


> I feel like I'm in the minority in that I prefer to NOT learn things by just "diving in". I am much more successful when I start from the absolute fundamentals.

A bit more off-topic, but this resonated with me. I too feel more comfortable when I start with the absolute fundamentals. When something does not work, knowing the fundamentals helps me to reason about why it does not work from the first principles. On similar lines, I did a relevant "Show HN" post here today:

Emacs4CL: https://github.com/susam/emacs4cl (35 lines of ~/.emacs to turn Emacs into Common Lisp dev environment)

It bothers me a little when someone new to Common Lisp or Emacs is encouraged to start off with Portacle or Spacemacs directly without appreciating the extensibility of Emacs and how SLIME fits in the environment. The Show HN post on Emacs4CL I have linked to above is an attempt to promote a more DIY approach to setting up one's development environment for Common Lisp without having to spend a lot of time.


I fixed CL as my first programming language to learn just 4-5 days back (after 3 weeks of mulling over what to learn) and had installed Portacle yesterday. A fellow redditor kindly listed out few steps like you suggested above, and I tried it for the sake of experience. It was not detailed as yours hence I was stuck until I saw this post on Reddit.

The instructions in your link were fantastic and easy. Thanks a lot for this !!


Thank you for the feedback. If you like Emacs4CL, please do take a look at the "Show HN" post for it here: https://news.ycombinator.com/item?id=25440690

Indeed the intention behind the .emacs and detailed documentation for it was to make it easy for beginners to set up a Common Lisp development environment with Emacs and SLIME quickly while understanding every step of the setup process. I am glad you like it!


Exactly.

Though, to be fair, if someone says they want to learn LISP and then you tell them to learn Emacs... well, now they have TWO problems! xD

I love and use Emacs. And I also, unsurprisingly, don't like or recommend that people start off with all of these "starter packs".

But at the same time, if you don't already know Emacs and you want to learn LISP, I don't know what I'd recommend.


For Clojure, VSCode with the Calva and clj-kondo extensions installed is a pretty good, free starting point.

Also, if you are used to the Jetbrains tools like IntelliJ, try the Cursive IDE (paid).


I actually like the VS code tooling better than Cursive. Not knocking it, but have never felt lacking doing Clojure in VS Code.


Cursive is free for non-commercial use.


> But at the same time, if you don't already know Emacs and you want to learn LISP, I don't know what I'd recommend.

Here is my attempt to make it easier to get started with vanilla Emacs + SLIME + SBCL without hiding the underlying details like a starter pack does: https://news.ycombinator.com/item?id=25440690


I feel like I'm in the minority in that I prefer to NOT learn things by just "diving in". I am much more successful when I start from the absolute fundamentals. There are objective pros and cons to either approach, but I suspect the success factor is based on one's personality (or some such).

I definitely find value in the project based approach, but I guess I'd say that I tend to want just a little bit more "here's the fundamentals" first, before transitioning into that mode. As a generalization. But Programming Common Lisp isn't bad for this reason, it's just a hair short of what I personally might consider "the perfect Lisp book" if I could imagine up such a thing.


Seconded. PCL ist in my eyes one of the best and most "modern" Common Lisp books around. SBCL is probably the best Common LIsp compiler and free on top of that. Paired with Slime and Emacs you have a professional development environment. I use it regularly.


> I installed SBCL, Slime for Emacs, and started working through the book Practical Common Lisp.

This is exactly the approach I took (~15 years ago) when I went all-in on Lisp for a few years. Don't know if it is still the best today, but it was a solid approach at the time.


> Possibly one could complement PCL with another book

I found a very good complement was Edi Weitz' "Common Lisp Recipes" from same the publisher.

http://weitz.de/cl-recipes/


If you mean Common Lisp, I'd say install SBCL and start playing with with the repl. Choose the editor you know best; even notepad is useful to copy and paste expressions to/from the repl. Any editor that's suited for programming will have a way to send expressions to the repl with a keystroke, which is much more comfortable. So basically, just pick VSCode.

With that, you're ready to go. Take just one book and work through it, you don't need the best book, but a book will be better structured and more complete than multiple blog posts from different people. Practical Common Lisp (http://www.gigamonkeys.com/book/) is good and freely available. I used ANSI Common Lisp (http://www.paulgraham.com/acl.html), from Paul Graham (https://news.ycombinator.com/user?id=pg), long time ago and it's also good.

If you are open to non-common-lisp lisps, I'd say pick up clojure instead of common lisp, it's more modern and thus you will find more community and up-to-date resources. Clojure for the Brave and True is a book that has been praised, but I did not read it. It has some jokes and humorous examples that might or might not suit you.


I'm doing Clojure for the Brave and True right now and it has been an amazing resource. It even incentivized me to get into Emacs as well, which has been a blast. I'm not a fan of the humor, but it does not get in the way at all.


Am a stalwart fan of the humor. And the cover with its dwarven warrior wielding his lambda hammer is a priceless inspiration to rise to the task and code.


VSCode has a Swank client that has a functioning REPL along with other goodies for interactive programming.

https://marketplace.visualstudio.com/items?itemName=rheller....


SBCL is great, but one should not use an editor, which doesn't have proper paren matching and some indentation support. That is just making your life miserable. So SBCL+Slime+Emacs is a great combination. Or alternatively, get the free version of Lispworks.


Whoa, that's a big jump you made there from paren matching plus indentation to emacs. If he is just learning, emacs might be overkill. I was just simplifying the minimum requirements. But I agree with you about parens. This is not 100% popular but for a newbie I'd add the following recommendation:

Make sure your editor has parinfer available. Not parindent, parinfer. People swear by parindent, but you don't need it on day one. Just try it later on. Parinfer is your friend.


Yes, it is a step, but learning the very basics of emacs isn't that hard either. I just cannot bear the view of someone trying to edit Lisp code with an editor without the basic support. This easily leads to all the horror stories you can read on the internet about Lisp :). Also, with Slime you get a great integrated environment. You can evaluate functions directly from the sources. Unless you plan to go with one of the IDEs, Slime is a great Lisp environment. Once you know Emacs+Slime, you won't need any other environment, so why not start with it?


"If you mean Common Lisp, I'd say install SBCL and start playing with with the repl"

I meant any lisp. Common lisp, clojure, ccl. I am new to this so did not have a choice. But in this thread I get the feeling that common lisp is the most suggested.


If you want a bunch of Lispers to recommend a Lisp, then it's hard not get the most traditional one recommended. If you think the value proposition of Clojure sounds interesting, then just go with Clojure. If you think Racket sounds interesting, just go with Racket. They're all Lisps, but serve different niches.


A whole lot of answers but very few questions - most importantly "Why do you want to learn Lisp?"

Are you new to functional programming and have heard that's the parent language? Do you know a statically typed functional language and want to learn a dynamically typed? Are you looking for something practical you can interop easily with other languages with? Are you looking for a good language to follow SICP with? Do you already know scheme but want to learn a true lisp?

Depending on the reason why there are lots of different recommendations. For example If you know Java, and want a more practical language with modern library support from the lisp family someone may actually say Clojure is the best choice for you. But if you know scheme and are wanting to learn an actual lisp, then that wouldn't match your needs.

Always be wary of people telling you what you should do without them knowing why you want to do it. Not because they don't mean well, but because the only way they can answer is by projecting their own reason "why" onto you - which in most cases isn't applicable.


Yes, "Why do you want to learn Lisp?" is a good question.

If the author wants to use Lisp because he/she thinks metaprogramming is interesting, or has read about the benefits of interactive programming, Common Lisp is the choice here.

If the author wants to use Lisp as a way to get a deeper understanding of important computer science topics, I think Scheme is the best choice and with this, following the SICP book.

If the author is interested specifically in functional programming and wants to get easy employment doing it, he/she should take a look at Clojure, Ocaml, and F#.


Yes, "Why do you want to learn Lisp?" is a good question.

If the author wants to use Lisp because he/she thinks metaprogramming is interesting, or has read about interact


Since you're a Vim user like me: I've found Emacs Lisp a good way to accidentally learn Lisp!

Like there are many Lisps, there are many Vims. Spacemacs is a Vim for Emacs or inside Emacs: https://www.spacemacs.org/

It's quite powerful. And it can be argued that Emacs is highly extensible - because it's written in a Lisp. Looking under the hood and hacking on the editor is a lot of fun and very informative. And also horrible and bad. But in a good way!

And almost completely unrelated: I very much enjoy the Structure and Interpretation of Computer Programs book and online lectures: https://ocw.mit.edu/courses/electrical-engineering-and-compu...

The video lectures were recorded in 1986!: https://ocw.mit.edu/courses/electrical-engineering-and-compu...

And they're still amazing.

(But people all think very differently and what works for me may not be your cup of tea!)


There are a lot of classics such as SICP and The Little Schemer, and I dearly love them all and consider them all to be canon that everybody should read at least twice. But, for an easy/fun on-ramp, I think that there are three new contenders that are much better for getting a feel for things. Pick one according to your tastes, or burn through them all in a couple weekends and then decide.

If "functional programming for the enterprise" sounds good to you, read Clojure for the Brave and True.

If you're more interested in a truly mature language with a more academic community, read Land of Lisp.

If you're looking for a simple language that's easy to learn, or if metaprogramming is really your jam, read Realm of Racket.

As far as editors go, just start with whichever one you personally like best. They're all fine. I wouldn't bother spending much time worrying about that until after you've confirmed you want to stick with it.


Re language choice, you should be aware that CL is a massive language and requires you to know a lot of things about it to be efficient. With Scheme (Racket), you'll be able to ramp up easily as it requires less knowledge (as long as you are not doing metaprogramming). You also have the option of using Scheme itself to have something even simpler (Chez, gerbil, lots of choices here).

So you should ask yourself what your use for Lisp is. If it's just for fun, I'd go with the simplest.


Realm of Racket doesn't teach you about metaprogramming though.


Good point. For that part, my favorite guide is https://www.greghendershott.com/fear-of-macros/


I didn't go far with Lisp but I had fun with The Little Schemer as a first contact.


First you have to choose your flavor. If you want to use JVM, probably clojure. Otherwise Scheme, Common Lisp and Racket. Scheme is rather minimalistic, Common Lisp is very functional and Racket is the most modern one I guess. I ended up with Common Lisp and I rather don't look for change. SBCL is implementation I use and like it. Probably the best one and quite portable.

Emacs seems the best choice for Lisp, since it is scripted in Lisp and it's best adapted to it probably. However when I started, I was already so used to vim that I kept going with it. Maybe not the best option, but it's ok, maybe just a little bit more effort to automatize some stuff.

If you choose Common Lisp, this is probably the best book for start: http://www.gigamonkeys.com/book/ . Anyway be prepared, Lisp is not easy to grasp at first, but as soon you do, you will probably love it and appreciate way it is. :)


> Lisp is very functional

just to point out i believe 'functional' here means 'has lots of functionality' not 'more suited to functional programming' - in that regard scheme (and racket) are more 'functional' than CL


Emacs is probably the best editor for Lisp, but we have other good choices nowadays (progress!!): SLIMA for Atom, 2 VSCode extensions, Vim of course, Jupyter notebooks, and more: https://lispcookbook.github.io/cl-cookbook/editor-support.ht...

Note that getting started with Emacs, Lisp, SBCL, Quicklisp and Git is possible in 3 clics thanks to Portacle (http://portacle.github.io/)


Common Lisp programmer here.

https://stevelosh.com/blog/2018/08/a-road-to-common-lisp/

That's the best article I know on the matter.


When hackers[1] wax poetic about lisp, they focus on the core properties of the language (-family) that aren’t found in other languages. The meta-circular evaluator (lisp interpreter/compiler in lisp), “homoiconic” syntax (enabling easy modification of code), and others. These are what stuck with me most strongly.

ClojureScript (cljs) (and Clojure) I would recommend as practical, but simple and approachable dialects.

Scheme is a good, simple dialect to learn if you’re just looking to grok lisp in “maxwell’s equations” elegance (but not work in it). Not nearly as many libraries written for it as Common Lisp has, or Clojure with JVM interop, or CLJS with javascript+node interop).

Whether you use Scheme or cljs (or another~), I recommend SICP[2] “Structure and Interpretation of Computer Programs”, free online from MIT press. There’s even an interactive, editable version online [3] (though it doesn’t support saving reader code)

[1]: http://www.paulgraham.com/lisp.html

[2]: https://mitpress.mit.edu/sites/default/files/sicp/index.html

[3]: https://xuanji.appspot.com/isicp/


Haven't seen it mentioned, Paradigms of AI Programming by Peter Norvig is another good introduction to Common Lisp. It focuses on classic AI algorithms which showcase the strengths of the language well. It's available online here https://github.com/norvig/paip-lisp


The Little Schemer series is a good introduction to Lisp/Scheme parenthesis-style recursive programming.

https://mitpress.mit.edu/books/little-schemer-fourth-edition

https://mitpress.mit.edu/books/seasoned-schemer-second-editi...

https://mitpress.mit.edu/books/reasoned-schemer-second-editi...

They’re written in a Socratic way, as a series of questions and answers. A good way to learn is to follow along and answer them yourself using Racket (before turning the page and seeing the answer). Racket is quick and easy to setup and use:

https://racket-lang.org/


Is there a good argument against Clojure in this case? My impression is that it's a good lisp and you can get actual work done in it which is an advantage over some of the other options.


The main issue with Clojure is probably its tight integration with the various host platforms. When you get a stack trace in Clojure/ClojureScript, you basically get a Java or JavaScript stack trace, so there is some expectation of familiarity with the host platform. If you already have some experience with the host, then this shouldn't be a big issue, but it's a dealbreaker for some people.

Another issue has to do with startup time. The Clojure application bootstrap process is relatively slow, i.e. start-up might take 1 second, so it's great for server applications, but less great for Android apps or other CLI scripts that expect require instant startup. It has been approached in different ways, e.g. compiling Clojure with Graalvm native image or using ClojureScript instead of JVM Clojure. The latest solution is Babashka which provides a variant of Clojure specifically for writing CLI scripts.

Otherwise, Clojure is an excellent language which both modernises Lisp syntax significantly and implements a very well thought out standard library for doing functional programming. There are many great features, but the standout ones are probably the persistent data structures (which syntactically act both as data structures and functions) and parallelism/concurrency support. It's also very natural to do interop with the host platforms (Java, JS, .NET) and the data-oriented style of programming makes communication between backend (Clojure) and frontend (ClojureScript) extremely simple. So it's pretty much the perfect full-stack language for information systems. I would take a look at the rationale: https://clojure.org/about/rationale


>Otherwise, Clojure is an excellent language which both modernises Lisp syntax significantly and implements a very well thought out standard library for doing functional programming. There are many great features, but the standout ones are probably the persistent data structures (which syntactically act both as data structures and functions) and parallelism/concurrency support. It's also very natural to do interop with the host platforms (Java

Absolutely everything mentioned above in this quote is available in Common Lisp as well by just loading the needed libraries.

>Another issue has to do with startup time. The Clojure application bootstrap process is relatively slow, i.e. start-up might take 1 second,

>The main issue with Clojure is probably its tight integration with the various host platforms. When you get a stack trace in Clojure/ClojureScript, you basically get a Java or JavaScript stack trace, so there is some expectation of familiarity with the host platform.

Correct. And there are no such problems in Common Lisp. Except if you want to execute CL in a JVM, in which case the available implementation, ABCL, does take a slow time to start. Otherwise it's a great implementation.


>Is there a good argument against Clojure in this case?

I use Common Lisp and my main argument will be that Clojure isn't an "interactive programming" language like Common Lisp, Smalltalk (and Pharo, Squeak, Scratch) are. And, for me, this is removing one of the main, core advantages of Lisp.

Dispensing with the interactive programming features is, IMO, a step backwards in the state-of-the-art. Common Lisp ADDED all the improvements in the state of the art: Interactive programming from Smalltalk, lexical scoping from Scheme, various high performance/low level features from StarLisp and ZetaLisp, a very powerful OOP system, etc. And then, thanks to it being highly extensive, almost any feature can be added to it.

Clojure features like threading macros, immutable seqences, software transactional memory, and others, are already available in Common Lisp by just importing (loading) the respective library.

One of Clojure's main advantage is to be able to call Java libraries. But, surprise, you can do this in Common Lisp too, easily, by using the Armed Bear Common Lisp (ABCL) implementation. Which runs on the JVM too and makes the process of calling Java libs really, really easy. I have made a working example here, calling all the Swing UI library (java) from lisp:

https://github.com/defunkydrummer/abcl-jazz

It's true that Clojure has more widespread adoption in the industry and more libraries. However the library ecosystem on Common Lisp is decent.

>and you can get actual work done in it which is an advantage over some of the other options

This implies you can't do "actual work" in, for example, Common lisp. Which is not true, since there are companies that, in this very moment, are doing well paid, critical commercial work using Common Lisp.


Clojure is quite capable in interactive programming, through its REPL, so you must be talking about the lack of a condition system in the clojure core.

But Common Lisp features like the condition system are already available in Clojure by just requiring (loading) the respective library. :)

As an example, see https://github.com/clojureman/special . Nice thing about this repo is that it points to other options re. conditions with pros and cons of each one.

Now that I think of it, you might also be referring to the fact that Common Lisp can load libraries through the REPL. Clojure can also do this through an alpha feature, add-lib, that you can already require in any project.


What i'm talking is about the following:

- Able to easily modify (and recompile) a function while your code is running

- Able to redefine a class and then change existing instances so they use the new class definition

- Able to sabe the complete running state of the system (the "image" of the system, including state of all variables, data, loaded libraries, compiled functions, etc) into a file so it can be restarted later, just like Smalltalk does.

- Able to inspect any stack frame at will and to restart execution from any chosen stack frame

These are just a few of the feature that Common Lisp has and that are part of what an "interactive language" is. Common Lisp brings all these features, they work seamlessly, without any sweat, working reliably and efficiently.


> - Able to easily modify (and recompile) a function while your code is running

I do this all the time with Clojure at work. I will have my application running (web app) with two repls in emacs. One is connected to the ClojureScript repl and one to the Clojure repl. I am able to make changes to both front end code and back end code on the fly by changing a function and then evaluating the function into the repl. I can start the application when I get in to work in the morning and have it going all day a while I'm doing my work.

> Able to sabe the complete running state of the system (the "image" of the system, including state of all variables, data, loaded libraries, compiled functions, etc) into a file so it can be restarted later, just like Smalltalk does.

> - Able to inspect any stack frame at will and to restart execution from any chosen stack frame

Those are really cool features, are they in the base language or are they libraries that you would need to include?

If I may ask, are you using Common Lisp professionally? If so, what kinds of applications do you use it for? I've had this notion, as many others seem to have in this thread, that you don't really do anything professional with CL but I realize it is just ignorance on my part.


>I do this all the time with Clojure at work. I will have my application running (web app) with two repls in emacs. One is connected to the ClojureScript repl and one to the Clojure repl. I am able to make changes to both front end code and back end code on the fly by changing a function and then evaluating the function into the repl

But since you can't arbitrarily inspect and restart any start frame, you don't really get the interactive programming experience.

On CL, for example, when you hit a runtime bug that is uncaught, you get the debugger window which shows not just the "stack trace" but the complete stack FRAMES that you can inspect. So let's say deep down you find where the error originated and the states of the variables.

You can then jump to the definition of the offending function, edit the function, recompile it, (optionally) change any variable on that stackframe, and then continue the execution by restarting specifically at that stack frame.

In this way, the feature of "modify a function while the code is running" becomes way more meaningful. The program evolves as it runs, as if it were a lifeform.


Ok, I have to admit, 2 and 3 can't be done at all in clojure, that I know of. The 4th one can be done through libraries, as I said, and the 1st one is out of the box, though. So perhaps saying that clojure does not enable interactive programming is a little bit harsh / absolute; but I agree that CL is more flexible in those regards.


What does Common Lisp have, in terms of interactive programming features, that Clojure (together with Cider and nrepl etc) lacks?



I've been programming Clojure for a while and I've dabbled in CL, and while the CL debugger is certainly nicer, I don't see a major difference in how you develop interactively. Could you explain where do you see Clojure falling short?



I tried Clojure a bit and, compared to CL, I find it bloated :S Installing a library takes ages, a lot of memory, and I can't do it from the REPL (so I must quit my development environment, and start it again). CL feels very snappy. I can even install a new library to a running web app. I know it's dangerous, but it works and it helped me already :)


Libraries can be installed from the REPL in Clojure but it does require a dependency ahead of time:

https://insideclojure.org/2018/05/04/add-lib/

Some of Clojure's other runtimes perform a bit better, Babashka, CLJS, CLR, GraalVM for different trade offs if you need something like a scripting language or native images etc

I'm sure CL is still quicker but there are options


Note that this needs to be required because add-lib is still alpha, but it is to be expected that once it is in the main deps functionality, it will come out of the box!


yes but clojure can get you a job


Probably more than CL yes, but thank you I create my own job.


One argument I can think of is that if your problem is not shaped in a functional way, then a functional programming language might be a poor fit for the job.

Common Lisp is multi-paradigm language that is pretty bendy with regard to absorbing new ways of doing programming. It gets actual work done as well.


How is it that you think Clojure has trouble doing things in a non-functional way? I'm just curious, as I work in Clojure primarily and may have a huge blind spot I'd love to clear out!


For starters you'd need to have imperative control structures like `while`, `continue`, `break` and a `return` that basically returns from anywhere. That can probably be built with macros.

Then you would need to have ways to mutate variables, so you'd need to stop using Clojure's persistent collections and instead use the ones provided by the JVM.

Overall, you can do it if you want to, it is just somewhat painful to do so and the language will fight you. This is like my who tried to write functional Python which is possible but then it is just a much worse Clojure.


I don't have much of experience with Clojure myself - the above might be my first impressions from the little bit where I've tried it. Well, let me try to fix them then, and ask some questions.

In Clojure, how do you usually approach problems that are shaped in an object-oriented way? In object-oriented languages, this usually includes either some sort of method calls (and therefore mutable state) or message passing (which usually involves actors, like Erlang processes). Passing all state around as function arguments is one way, but it becomes somewhat tedious as state grows large.


What would be an example of "problems that are shaped in an object-oriented way"? That just doesn't sound like a thing to me. That may originate from a bias you may have from developing primarily in OO languages.

Clojure does have constructs to manage state. You don't need to shove it all into your function arguments.


Sorry for the mind shortcut. By that, I meant all sorts of problems where multiple state-bearing entities communicate via message passing - usually implemented via method calls in OO languages.


Well Clojure most definitely does support state-bearing entities that communicate using message passing (channels / agents / atoms...) and, while I confess I that I personally don't use them in _quite_ the same way that I use objects and method calls in an OO language, I find that programming in OO and functional languages is kind of converging towards the same point: functional programming in the small (immutable value objects that are worked on using pure functions) and OO in the large (state-bearing entities communicating using message passing).



I'm aware of this. How do you achieve setters if the state you close over is immutable? Isn't that the default in Clojure, since it seems to aim for immutability by default?


Through an atom (https://clojuredocs.org/clojure.core/atom). The idea of accesing a closure that is mutable is as follows:

  (let [temp (atom 0)]
    (defn getter [] @temp)
    (defn setter [val] (reset! temp val)))
To implement an object, you would do something more like:

  (defn new-object [init-val]
    (let [temp (atom init-val)]
       {:getter (fn [] @temp)
        :setter (fn [val] (reset! temp val))}))

  (def obj (new-object 0))
  ((:setter obj) 12)
To define interfaces, you could check whether the map/object conforms to a spec, etc.

But obviously all this is not very idiomatic; in clojure you would keep those functions first-class through defn instead of tying them to the object / map, and would pass state as an argument. Something like:

  (defn getter [obj] @obj)
  (defn setter [obj val] (reset! obj val))

  (def obj (atom 0)) ; This gives you the ability (and need) 
                     ; to explicitly track the list of 
                     ; existing objects in use lest they are garbage collected.

  (setter obj 12)
If obj has structure (e.g. it is a map such as {:type :my.personal/type :val 12}) you can identify its type through the type keyval and can check conformance to a spec, etc.

As it was said in the previous post, it's equivalent. It's a matter of how to organize code.


That's a good explanation. Thanks!


You could have an atom that holds the state and a function which can update that atom. You might do something like the elm architecture where you pass a message to a reducer which produces the new state that the atom is set to. All the logic is contained in the reducer and is pure and immutable and the state change happens at a single controlled point.


OK. If I understood correctly, then you limit the mutable state to one point, and use functional logic everywhere around it. You can also optionally close over the atom to achieve encapsulation.

Thanks, TIL! That's equivalent to the "mostly functional" style that's doable in Common Lisp.


Yeah, Clojure is one of those languages where functional purity at all costs isn't really the goal. Like others have said its more about being careful how you set state and Clojure gives you loads of great functions for doing everything in a pure way. Its standard library is its greatest asset as far as I'm concerned


Exactly! This method of limiting the mutable part to one point is a pattern that is highly useful, and highly used, when working in clojurescript with react through reagent and re-frame, for example: you represent the whole state of your app in a tree of maps and define functions that, given a version of your app state, return the updated version. Then you just execute state-changing pure functions linked to a stream of events to move your one-point-mutable-app-state through a stream of valid states.

(and also obviously functions that map that state to HTML/CSS/SVG/etc.).


Exactly. Functional programming is pretty much all about being very mindful of when to use state vs pure functions.


Using state is not functional programming, so you're really saying that functional programming is all about being mindful when to use functional programming versus when to abandon functional programming.


There's also the added benefit of Software Transactional Memory being available for operations on said mutable state, in case you need to access it from multiple threads.


Apologies in advance for going on a slight tangent here but it's my view that defining getters and setters is not considered idiomatic OO code either. If one object is using getters and setter to access the state of another then this suggests that there feature envy and excessive coupling between those two objects. These days, I try to follow the Law Of Demeter (https://en.wikipedia.org/wiki/Law_of_Demeter) and avoid that sort of thing. The logic that calls the getters and settings should really be in a class with a single responsibility that we call by invoking its methods in a tell-don't-ask style. As others have already pointed out, we can do similar things in a functional language like Clojure by encapsulating state in an atom (or an agent) and applying pure functions to that state.


How is the VSCode support? I've only used IntelliJ + Cursive for Clojure and am quite spoiled. That's the only reason I might not recommend Clojure for a VSCode user. Now, if said user is interested in switching to Emacs or IntelliJ, I'd think it would be a perfect fit.


Nowadays, you can get VSCode support for Clojure pretty much out of the box with calva[1] extension working together with clj-kondo [2] almost without any configuration. It works great - I've switched over from Cursive and I'm not looking back.

[1] https://calva.io/ [2] https://github.com/borkdude/clj-kondo/blob/master/doc/editor...


I think it makes more sense to pick the language first and then find an IDE for it that you like instead of the other way around.


Chiming in since I'm a bit disappointed with Clojure VS Code support:calva (the clojure extension) works great, unless you also want vim bindings. In which case it's a bit of a cluster. It's documented and I understand why - but it's still a pain point (it makes the escape key not exit insert mode anymore, by default).

(nota bene: I understand these things are hard to solve and I don't mean to throw the stone without putting my own time on the line to fix it, but that's one reason I'm not using VS code for clojure. Doom emacs with cider is still better, even if not perfect). If people know of someone I could throw money at to solve the integration for VS code, I'd be happy to do that.

If you find a good/great experience for clojure with vim keybindings, I'm all ears.


Vim with the Vim-Fireplace plugin works great for me.


As a Lisp and Clojure beginner, ehhhh. I could get work done, but I depended on the terminal for REPL and compiling & running. I ended up using Emacs, which along with .NET were the only cases where VSCode didn't feel ideal for me.


Emacs and slime are great for lisp, but my experience is that learning all three at once is too much. Stick to vscode and install the lisp extensions (or sublime and sublime repl was what I learnt on) and work through the lisp koans (search on github you’ll find the repo).

Once you have the basics down then look into setting up slime and jumping down the emacs rabbit hole.


Emacs will probably be better in the long run for Lisp, but you can use any editor to begin.

For Common Lisp, SBCL [1] is probably the best free option. If you want to learn Scheme instead, Chicken Scheme [2] and Racket [3] are popular and good choices.

[1]: http://www.sbcl.org/

[2]: https://call-cc.org/

[3]: https://racket-lang.org/


I think you can use whatever to do Lisp. I'd start with something simple like Scheme, and definitely by watching and doing the SICP lecture recordings from now 34 (!) years ago: https://ocw.mit.edu/courses/electrical-engineering-and-compu...

Once you think you grok it, you can pick a Lisp that's closest to what other tools and frameworks you're used to. For me, I never actually did anything in Lisp for production use, but learned a lot from playing with various flavors of it.


> I think you can use whatever to do Lisp.

I'm not sure about that. You need an editor that automatically matches parens and other paired delimiters and keeps them balanced, like paredit.


I did kind of make the assumption that you'd have a code editor that has some form of paren highlighting, at least, though I've never actually found this to be a bigger problem in Lisp than other languages.


It's not paren highlighting: it's about making it impossible to create unbalanced parens.


At this point I don't see how I could make a suggestion that hasn't already been made. My only regret is waking up in the wrong timezone and being late to the party. I think it is great to see so much interest and so many answers to this question here on HN.

I suppose one suggestion I might make is to take a look at Janet after you have a chance to do some reading on lisp. It is practical and multi-paradigm like Common Lisp but adopts syntax similar to Clojure. Plus it comes in a small package and the docs for the core library are really nice.

https://janet-lang.org/


Books

-ANSI Common Lisp by Paul Graham -On Lisp by Paul Graham -Simply Scheme -The Little Schemer -Structure And Interpretation Of Computer Programs -Paradigms of Artificial Intelligence Programming

Implementations

Common Lisp - any should be fine, I’ve used sbcl and clisp

Scheme - I like gambit scheme. It has a macro system that can be used like described in “On Lisp”


The Hacker News Paul Graham?


He wrote his first product (Viaweb) in lisp and sold it to Yahoo!. (If a name has an exclamation and it's the last word in a sentence, do I follow it with a period like normal to avoid seeming overly enthusiastic?)

He wrote two books on Common Lisp and has his own Lisp reading list: http://www.paulgraham.com/booklinks.html. There's also, one level higher, a set of lisp links: http://www.paulgraham.com/lisplinks.html


Yes, "!.". I still remember a math problem when I was a kid, in which a sentence ended with "4!"...


Yes. I actually found out HN due to his lisp books, so for me is Paul Graham? The "On Lisp" Paul Graham? haha.


Yes


Michael Nielsen (one of the creators of quantum.country, often cited as a feedback-giver on PG's essays) has a short blog post introducing and exploring Lisp here:

https://michaelnielsen.org/ddi/lisp-as-the-maxwells-equation...

Its on the more academic side and focuses on the Scheme dialect, but is well-written


I’d start with Clojure if I were you. Then the leap to a more traditional lisp will be much easier.

That being said you might have no desire to leap at all - Clojure is a powerful language with a great ecosystem (especially if you rope in Java interop)


Why not go through some of the classic lisp programming books like sicp[1] or htdp[2], since both are freely available?

[1] https://mitpress.mit.edu/sites/default/files/sicp/index.html

[2] https://htdp.org


The very reason I find Lisps enjoyable is all the things an editor can do for you with a Lisp. Smartparens, rainbow parens, easy eval of forms (+ pprinting, macroexpand, inline replace etc), jump to definition, for Clojure - contextual awareness of the namespace and REPL session you're in. Probably forgetting a number of things. Without these there wouldn't be much for me left to like about programming in a Lisp. As far as I'm concerned, learning to use the editor well is as important as learning the language itself.

I only know Emacs well. Checked out VS code for Clojure a while ago and it wasn't even close. Clojure IDE "Cursive" is supposed to be good, but never tried and not sure if you want to invest time in an ad hoc IDE. It seems to me lispers don't want to discourage people by recommending Emacs, but at the end of the day, most people who stick with it tend to be Emacs users.


> Clojure IDE "Cursive" is supposed to be good, but never tried and not sure if you want to invest time in an ad hoc IDE.

Cursive is just a Clojure plugin for IntelliJ , nothing ad-hoc about it. IntelliJ is the favourite IDE for lots of people - especially Java devs - so it's an obvious choice for Clojure developers.

I've programmed Clojure professionally for several years now and have seen maybe 50 different editor setups in person and I've yet to be significantly impressed by emacs. It does seem to offer most of the stuff that comes out of the box in IntelliJ (with the Cursive plugin), but only after many hours of setup and days to weeks of getting comfortable inside its somewhat antiquated UI paradigm. Nothing against emacs, but I just haven't seen the great case for using it over something like Cursive, other than if you need to develop commercial software and don't wanna buy a commercial licence for Cursive. A bunch of people at my old job actually switched from emacs to IntelliJ a couple of years into their Clojure journey.

I do see the obvious advantage of using emacs if you're already a heavy emacs user, however. And if some Clojure-specific kiler feature pops up in emacs, I'll probably switch to emacs too. Until then, I'll stick to Cursive which covers all of my various Clojure needs very well out of the box.


> Cursive is just a Clojure plugin for IntelliJ

Well, I'm ignorant about the IntelliJ ecosystem. Can I take some of what Cursive is providing and use it with Racket or Common Lisp?


No, Cursive is just for Clojure, not other programming languages.


I don't know what it is about ANSI Common Lisp but it wasn't just a good introduction to something technical, it was fun. I blasted through it in a couple days. I never do that. I usually can't wait to ditch whatever introductory text I'm using and get off the beaten path but I couldn't put it down.


I would start with Scheme or Racket that is based on Scheme. I would start with any Scheme interpreter like Kawa or Guile. If I would recommend any book it would be Sketchy Scheme by Nils M Holm (that I've read recently) https://www.t3x.org/sketchy/ it start with basics but it have lot of details and advanced stuff about Scheme and how it works. It also as title suggest intro to functional programming.

If you would like to learn on line (maybe using pdf book) you can try my Scheme REPL bookmarklet https://lips.js.org/#bookmark so you don't need to install anything on your computer, you can do that later.



It is a slightly older edition, though.


On Lisp by Paul Graham is a good start: http://www.paulgraham.com/onlisp.html

Edit: I meant ANSI Common Lisp. Thanks everyone!

(I wouldn't even recommend On Lisp as a second text, too much macrology).


On Lisp is mostly about macros (advanced). He has also written "ANSI Common Lisp" in 1996 which is a very good introduction text: http://www.paulgraham.com/acl.html


Maybe worth nothing that these days Paul Graham recommends Clojure: https://twitter.com/paulg/status/1240218967865778177


I would not start with OnLips it's pretty advanced book on Common Lisp. It's very good book but not for those that just staring out.


IMHO On Lisp is the best as a 2nd (or 3rd) book, but not the 1st. It really explains why Lisp once you understand the basics.



Lot of comments here, many good, so I'll try not to duplicate, but:

  1. Emacs is a hurdle, but one that's worth it when you use SLIME.
  2. I went through Barski's "Land of Lisp" and enjoyed it, but couldn't get the web server to work, so I tweaked it to use Hunchentoot[0]
[0] - https://github.com/npsimons/land-of-lisp-using-hunchentoot/c...



Why? The original site is still up.


You're right. HTTPS Anywhere takes me to https://landoflisp.com which is a placeholder webpage.


Pardon my plugging my own book, but you can read it free online: https://leanpub.com/lovinglisp and checkout the GitHub repo with examples. There are much better Common Lisp books for a broad coverage of the language. My book is a short tutorial followed by many example programs. The book is released under a Creative Commons license so you can find copies on the web, but probably better to read the latest version online.


This is a bit tangential but what helped me most in picking up Lisp was writing my own. Until I worked through Make A Lisp [0] I don't think I really "got" Lisp. You can work in whatever language you're familiar with. You build a Lisp similar to Clojure and learn a lot of important concepts by implementing them.

[0] https://github.com/kanaka/mal


I didn't write my own but started hacking[0] on an existing implementation -- you learn quite a bit about the underlying language by tracking down bugs as you implement (or port) features in the interpreter. I was trying to get the parser up to an actual parser for the language (which produces a lot of 'language learning experiences') but got distracted with adding unicode support (which hasn't really taught me anything new about scheme...)

[0] https://github.com/eponymous/yocto-scheme


I'm doing the same thing right now. I have tried to get into lisp a couple of times, but this time it's the first time I "get it".


For anyone who needs a "download and go" way to play with Lisp, Allegro offers a free version. It's one installation. For VS Code, I'd wire-up SBCL as others have said. It's a little touchy to get setup but we produced our product with it so it does work.

The whole issue of "flavors" largely comes down to one concept: Do you like the idea of functions and variables being in the same namespace (that's called a Lisp 1 like Scheme) or different (a Lisp 2 like CL). If you don't care, it doesn't matter which you pick.

If you're going to extend your Lisp app into production, you might want some of the many libraries that are available for CL. These cover just about every known topic and algorithm in comp sci and they're old and proven and just work everywhere, so that can be a benefit as you move to a non-trial app.

If you're going to distribute something written in Lisp (like an executable), then the flavor and implementation you pick will need to work all the way down your distribution path, and that can be challenging to get setup. One proven path is SBCL + Node.js + Electron to wrap your app for all three platforms.

Hope you love Lisp and get great things out of it!


OK, I want to know what's your product! (and if we can add your company to the "lisp companies" list https://github.com/azzamsa/awesome-lisp-companies ?)




I'm currently taking another stab at lispy-languages. I've tried it a few times in the past and I've always had a hard time coming back to it when something else intervenes. Usually self-inflicted because of some complex and unecessary environment setup involved.

I've lately had some success using vanilla emacs, Geiser and Guile (or MIT) Scheme. If you want to work through sicp, the little schemer [1], or my current favorite "Essentials of Programming Languages"[2], then that's the perfect setup. Racket will work too, but if you're using emacs anyway then it's just as easy to get going with Guile or MIT.

I'd recommend getting familiar with largely vanilla emacs[0] rather than a curated kit, but it will require a little bit of additional investment. Additionally, you'll be getting acquainted with emacs-lisp (elisp), so you'll be swimming in lisp languages.

I'm not a fan of VS Code and only use it for work when I have to (and then only when I can't use vim). I'm sure it'd work, vim too, but there are an awful lot of emacs/lisp resources out there and it's helpful to take advantage of what's available.

[0] https://sanemacs.com

[1] https://www.amazon.com/Little-Schemer-Daniel-P-Friedman/dp/0...

[2] https://www.amazon.com/Essentials-Programming-Languages-Dani...


Land of lisp by Conrad barski is a pretty great book too.


Do you plan to learn as a LISP dialect as a purely academic exercise or to build something with it?

If you want build it as a tool, I’d recommend Clojure.

I’ll be happy to teach if you’re interested

https://twitter.com/akakopos/status/1331613484623093765


If you're set on using vim slime is great. Basically you bring up the REPL in another tmux or screen split then you can just pipe your forms to it.

https://github.com/jpalardy/vim-slime

Here's a few previews for fun books I enjoyed, land of lisp and realm of racket by conrad barski

https://books.google.ca/books/about/Realm_of_Racket.html?id=...

https://books.google.ca/books?id=9apQfCRhvm0C&printsec=front...


It took building a lisp for me to finally understand them .. I recommend http://peter.michaux.ca/articles/scheme-from-scratch-introdu...


Switch from vim to use evil-mode in emacs, perhaps via the spacemacs or doom emacs emacs starter projects. These present the vim editing interface, but implemented in emacs.

Then you're using emacs. Play around with emacs lisp customizing it and writing utilities for yourself to do editing tasks and whatever else you can think of. The community of emacs lisp programmers has lots of common lisp programmers. It's a serious-enough lisp to get started with, with sophisticated macros and several features from common lisp.

Make sure you use paredit. It's basically essential when learning lisp to use an editor that automatically matches parens and keeps them balanced. Beginners who complain about the parens are making that mistake.


If you want to learn a LISP dialect just for fun and/or enlightenment, I would say you want either a Scheme (Guile or Racket) or Clojure.

Some people will argue that Clojure isn't a real LISP, which is fine. They're probably right. But it's an elegant and well-designed language that has a lot of the same features and feeling of a LISP/Scheme.

I know I could be burned alive for saying it, but Common Lisp is pretty ugly, IMO. It's "pragmatic" and has a bunch of libraries and functionality and whatnot, but it's not as fun or elegant as a minimal, pure, Scheme.


Why is common lisp ugly? Many people here suggested common lisp. I was considering it. I like to learn for fun but I am looking for something practical. I will want to build some useful apps in the end with it.


I wouldn't go so far as to describe Common Lisp as ugly but it's an old and fairly large language that carries a lot of baggage does a few things differently from modern languages and operating systems. Personally, I tried to learn Common Lisp 15 or so years ago and found it difficult to get the hang of how it works.

The Lisp that I eventually got into is Clojure. If you're familiar with either Java or JavaScript then that's what I'd advise looking at. The language itself is well designed and elegant and if you understand the platform that it's running on (JVM or JavaScript depending on which variant of Clojure you're using) then that's very helpful. For me, being able to add a dependency on basically any Java library and use it without too much hassle is brilliant but I'd still love the language even if that wasn't the case.


This is mostly people complaining about weird names like RPLACA or having to type #' because it's a Lisp-2. From the MIT perspective it can feel inconsistent but for such an old, practical language, it is really well designed.

I mean, if Common Lisp is ugly what are Perl and C++ then.


also ugly :)


Even uglier


Caveat: I'm not an expert in any of it. I've played around with Guile Scheme, Common Lisp, and did a (small) real-world work project in Clojure.

I mean, Common Lisp is perfectly fine. And if you want to use it to write real apps, it's a good choice. Especially if you will have dependencies to manage (see quicklisp).

There's just a few little things that I don't like as much about it.

There's a holy war about "lisp-1 vs lisp-2 (or lisp-n, really)". Not much point in debating that, but scheme is a lisp-1 and CL is a lisp-2.

I like that schemes tend to use #f for false and #t for true, whereas CL just uses nil for false, and for empty-list, and anything else for true (which is usually the symbol t in practice).

I like the way things are named more in Schemes: map vs. mapcar, number? vs. numberp, etc.

I like that the Scheme standards guarantee tail-call-optimization. I believe all popular CL implementations do implement it, but it's not required by the standard.

CL has the ugly loop macro, and Schemes emphasize recursion more (also has `do`, though).

Schemes have "hygienic macros" which I like much more than unhygienic macros.

These things mostly don't matter, honestly. It's all bikeshedding. Lisps and Schemes are very very similar and also very different than most other languages. You can't go wrong with either.


I wouldn't call it ugly, more. . . untidy.

Common Lisp grew by accretion over a fairly long span of time. Consequently, it has varying conventions, inconsistent ways of working, and a whole lot of TMTOWTDI going on.

That said, perhaps we should be careful what kind of house we're in before throwing stones. Exactly the same accusation could be leveled against Java, Python, C++, and Haskell.


drracket is one of the more impressive pedagological IDEs i’ve ever seen.


About the editor:

In general you can use any editor, but there are some features which your editor should have to make your life easier. I wrote a blog post about it some time ago: https://klibert.pl/posts/tools_for_lisp_syntax.html

Basically, syntax highlighting, automatic matching paren insertion, ability to jump to a matching paren are the baseline. If you can get those with a plugin to VSCode or Vim, you're good to go.


Stock Vim got all of that.


You might be interested in this old discussion:

https://news.ycombinator.com/item?id=713015


The Lisp Tutor Jr was amazing. It gave you problems and "watched" as you type the solutions in Lisp. It seems to be down![0]

Does anyone know if there's a mirror somewhere? I'd gladly host this in a droplet and make it public if someone has the source.

[0]http://reed.cs.depaul.edu/peterh/Tools/lisptutor.html


Check out Gerbil Scheme. It has a lot of great features included in its standard library[0], and is currently the fastest Scheme around[1]. The only downside is no Windows support at the moment.

[0] https://cons.io/

[1] https://ecraven.github.io/r7rs-benchmarks/


I asked this in Reddit a while ago and got these answers: https://www.reddit.com/r/lisp/comments/iwz36s/list_of_lisp_e...

VSCode will be fine for editing Lisp, there's a good syntax highlighter extension too.


I thought The Little Schemer was a fun text that is presented in a unique way. There's also another fun one called The Land of Lisp.


How to Design Programs, Second Edition

https://htdp.org/2020-8-1/Book/index.html

It's a good introduction to programming in general and uses a series of "student language" dialects of Racket, which is in the Scheme/Lisp family.


I forgot to ask in my main question. I can't edit it anymore.

I am seriously thinking of learnijg common lisp. Thank you for all the suggestions.

Is it possible to build web apps in common lisp or any lisp? Any frameworks available?

Is it possible to build multithreaded apps that use multiple CPU cores for performance? What is used? POSIX threads?


If you are thinking on doing web apps, I think Clojure is the best option, as it enables you to write clojure to target both server (either in clojure or clojurescript) and browser (with clojurescript, that compiles to javascript), and share code between those seamlessly (for example, protocols, specs, business logic, etc. that you may need in both sides).

That's the most extended option by far, but I'm sure that you will find other lisps that compile to javascript (not that I know them).


Yes, Clojure

> Is it possible to build web apps in common lisp or any lisp? Any frameworks available?

Clojure would be good because it has lots of users. Many web apps in production. It might be good to start out with luminus for Clojure, but maybe even before that, try to get a simple Ring and Compojure thing going where you can send a request and get feedback.

> Is it possible to build multithreaded apps that use multiple CPU cores for performance? What is used? POSIX threads?

Clojure is awesome for multi-threading. That's one reason Clojure is functional/immutable by default.

Also, you get access to many libraries in the language hosts (Java, Javascript). That could be a big reason for its success.

Good luck in your pursuit!


The "web apps" problem is the most important one, I think. The short answer for us was the strangeness of building HTML or GUI UI's with Lisp. The solution we used was to make our UI in HTML/JS/Angular and have it talk to a Lisp backend with Node.js.

In this way, we use Lisp for what it's good at and use HTML/JS to make a modern front end.



>Is it possible to build web apps in common lisp or any lisp? Any frameworks available?

Yes, many.

>Is it possible to build multithreaded apps that use multiple CPU cores for performance? What is used? POSIX threads?

Yes, threads, there's many libraries also for channels, software transactional memory, etc.


>I use VS Code and Vim. Are they suitable for learning Lisp?

Better install Portacle, that's the only thing you need to install to edit, compile, and debug Common Lisp code.

Then you can learn by reading a good book like a "Gentle introduction to Symbolic Computation" or "Practical Common Lisp".


This book made me fall in love with Lisp: Land of Lisp - https://nostarch.com/lisp.htm

I found it super helpful understanding everything there is about Lisp, and you can move from there.


I would start with Dr Scheme (now called Racket/PLT Scheme). That is what CS301 at UT Austin started with https://plt-scheme.org/ back when I was an undergrad in 2000


Is there a full featured editor that's hosted in the SBCL image itself? I vaguely recall CMUCL had something of the sort. It used to be you had to actually specify GNU Emacs, but nowadays it's pretty much the only Emacs anyone means.


Yes, there's the Lem editor (unrelated to CMUCL or the SBCL project itself): https://github.com/cxxxr/lem/ (also works for more programming languages) (and also, rather ipython-like, cl-repl: https://github.com/koji-kojiro/cl-repl/)


I worked my way through Land of Lisp a few years ago and had a good time with it. I had already done some Lisp programming before, but I learned a bunch from Land of Lisp and had fun in the process.


Somewhat orthogonal to the question, but if you're looking for good programming exercises (for any language!) Advent of Code adventofcode.com is always a great place to look.


I really enjoyed reading 'The Little Schemer' book. It teaches the Scheme language, which is a Lisp-1. It was entertaining due to the novelty of its format.


I'm just wondering, besides being more knowledgeable about languages in general, are there any use cases for Lisp dialects nowadays?


Some pointers: Scorecloud (https://scorecloud.com/), a music composition software (you sing, it writes music) comes from research, and is built in Common Lisp.

pgloader was rewritten from Python to Lisp: https://tapoueh.org/blog/2014/05/why-is-pgloader-so-much-fas... because of Python's poor performances and threading capacities.

A theorem prover used in the industry: https://github.com/acl2/acl2

A Lisp vendor selling semantic graph solutions: https://franz.com/ (see also its success stories for industry examples)

Here's a sadder story: a team switched from CL to Go for production, but still use CL for prototyping: https://lisp-journey.gitlab.io/blog/pro-mailing-list-on-comm...

Some use CL in bioinformatics (and claim it's the best tool for the job). For example, they create a new Lisp implementation: https://github.com/clasp-developers/clasp

More success stories: https://lisp-lang.org/success/


Here are my recommendations on this topic:

- Choose Common Lisp because it has been the most popular dialect of Lisp in the overall history of Lisp. It is more convenient than Scheme if one decides to develop serious software in Lisp. Clojure appears to be more popular in the technology industry than Common Lisp among organizations (my workplace included) that use Lisp. I still recommend Common Lisp because I believe that it is more likely that one would work on an independent open source or hobby Lisp project than one would encounter one of the rare organizations who use Clojure at work.

- Choose SBCL (Steel Bank Common Lisp) as the implementation.[1][2] It is the most popular[3] Common Lisp implementation and is recommended in many online discussions. CCL (Clozure CL, not to be confused with Clojure which is a separate dialect) is also another very good implementation.

- Work through this book: Practical Common Lisp: http://www.gigamonkeys.com/book/ (available in print too if you search online). Just use a modern alternative to Lisp in a box when you reach Chapter 2. In fact, I encourage using vanilla Emacs and setting it up with SLIME and Paredit yourself. See Emacs4CL for example.[4]

- A Vim user may consider installing Slimv or Vlime[5]. Slimv and Vlime offer an environment similar to Emacs/SLIME. They display the REPL in a Vim buffer. Slimv also comes with Paredit mode that makes typing and executing S-expressions quite convenient.

- In case you want to postpone setting up Emacs + SLIME or Vim + Slimv/Vlime until a time you have become more familiar with the language, you can also execute your Lisp source code files from the shell.[6]

- Optionally, keep another implementation of Common Lisp. Common Lisp is a standard that is implemented by various implementations. Each implementation may have its own extensions or implementation-specific behaviour regarding error handling, command line options, FASL format, unspecified behaviour, etc. Experimenting with concepts with another implementation of Lisp occasionally may offer some perspective about how some things could be different in different implementations. I keep CLISP around for this purpose.[7][8]

[1]: Install SBCL on macOS: brew install sbcl

[2]: Install SBCL on Debian-based distro: apt-get install sbcl

[3]: State of Common Lisp Survey 2020: https://docs.google.com/forms/d/e/1FAIpQLSfg7UJRKrkI3OjOHWL4...

[4]: Emacs4CL: https://github.com/susam/emacs4cl

[5]: Lisp in Vim with Slimv or Vlime: https://susam.in/blog/lisp-in-vim-with-slimv-or-vlime/

[6]: Load (execute) code in a file and exit: sbcl --script foo.lisp

[7]: Install CLISP on macOS: brew install clisp

[8]: Install CLISP on Debian-based distro: apt-get install clisp

Disclosure: I am the author of [4] and [5].


Racket is explicitly designed as a teaching language and I would highly recommend Beautiful Racket as a starting point.



SICP and umb-scheme is how I learned as part of the university course with fairly advanced exercises.


Has anyone found a good beginners up and going setup for Lisp and VSC?



Scheme or Clojure. Get The Little Schemer book.


Probably the best way to get started just to install SBCL and start typing stuff in at the REPL. Lisp is a very immediate language; you can type an expression in and the REPL will instantly evaluate it and show you the results. Many other languages, such as Python, Ruby, and JavaScript, actually borrowed this feature from Lisp.

You're going to need an editor to write long-form programs. Vim and Visual Studio Code are fine, but the ne plus ultra of Lisp editors is Emacs ( https://www.gnu.org/software/emacs ). Emacs comes with an excellent Vim-emulation mode, so if you cannot leave behind your vi muscle memory, that's always available to you. Another feature of Emacs is, it contains, and much of it is written in, its own dialect of Lisp! The upshot of this is you can usefully extend and customize your editor by evaluating a few Lisp expressions. Playing with Emacs Lisp is a great way to learn how to use the language to do "real work" during your experimentation. Emacs has a package available called SLIME, which allows it to talk to a standalone Lisp environment such as SBCL, send it expressions to evaluate, and get results. SLIME also has LSP-like features to show documentation on the Lisp functions you've defined. Vim and Visual Studio Code can speak SLIME's protocol with the proper add-ons, but the integration is not as tight as with Emacs.

If Lisp seems overwhelming, it's because it's more of an idea than a specific language. There are three varieties of Lisp you should be aware of. Well, four if you count Emacs Lisp, but the standalone ones are:

* Common Lisp

* Scheme

* Clojure

Of these, the best place to start is probably Common Lisp. It is a comprehensive language which has been used in real-world software engineering projects since the 1980s, and it has a very strong community surrounding it. There are a few implementations, both open source and proprietary. The most favored one today is SBCL: https://www.sbcl.org

Scheme is much simpler. It is more of a language core used for teaching, and for providing a basis for a more feature-rich programming language. There are many implementations, most of which provide their own extensions to the core language; my favorite for getting work done in a Unix-like environment is GNU Guile: https://www.gnu.org/software/guile

Clojure is a language that is designed to interoperate well with the JVM, and to promote Rich Hickey's ideas on functional programming. It is a very opinionated language, more so than the other two, and you may find yourself struggling more if you don't do things the Clojure way. Personally, I like it less than the other two, but that's a matter of taste and you may find it more useful.

Over time I hope you will have the opportunity to try all three. Each has something different to offer and each can be learned from.


If you're on Arch Linux, you can install the `lisp` package from AUR, then type `lispi` and then `(+ 1 2)` for adding 1 and 2. Don't type in the backtick quotes. Press `ctrl-c` to quit.

If you install `clojure` you can start the interpreter with `clj` and also type in similar expressions, like:

  (* 3 7)
There are a couple of differences to Common Lisp, though.

The fun thing about Lisp is that you can pass any number of parameters to functions, like "+", so that expressions like this also works fine:

  (* 1 2 3 4 5 6 7)
The next thing to know is that the first element within () is interpreted as the function, while the rest are interpreted as parameters. Then how do you represent a list like (1 2 3) without Lisp thinking that "1" is the function, you surely ask? You prefix it with ', like this: '(1 2 3). If you type '(1 2 3) into the `lispi` or `clj` prompt, they will print (1 2 3) right back at you.

A fundamental concept in Lisp is to get the first element of a list (the head) or the rest of the elements (the tail). For historical reasons the head is called CAR and the tail is called CDR in lisp. Everyone has just accepted that this is the way of Common Lisp by now. In Clojure, "first" and "rest" are used instead of CAR and CDR, as the heathens they are.

Since regular for loops are for wimps and snowflakes, iterating in traditional Lisp mainly centers around how to do the same thing using CAR, CDR and recursion.

Before we can do that, let's define a function that adds 2 to the given number:

  (defun addtwo (x) (+ x 2))
Note that "defun" is the function for creating functions that takes, roughly speaking, three parameters: the function name, the function parameters and the function expression.

If you type it into "lispi" you can use the function afterwards, and get the result 42:

  (addtwo 40)
Also, all lists in lisp are really just the head and the rest, so creating lists can be done by combining a head with the rest of a list, using cons, like this:

  (cons 1 ())
Which is equivalent to this (but signifies that quoting was intended):

  (cons 1 '())
And this:

  (cons 1 nil)
All three of the above expressions returns a list with one element (1), which means a head of 1 combined with an empty tail. Lists are constructed by appending heads to existing (or empty) tails.

Creating a function that takes apart a list into a head and a tail and then combines them again can be done like this:

  (defun combine (xs) (cons (car xs) (cdr xs)))
"xs" is the name of the function parameter, which is a list.

The combine function can be called like this:

  (combine '(1 2 3))
And will return:

  (1 2 3)
If you wish to edit code in a file instead of interactively, where the arrow keys may not always work, try putting this in a file named "main.lsp":

  (defun hello ()
    (write-line "Hello, World!"))
Then run the desired function with:

lisp main.lsp hello

Now to create a for-loop replacement in Common Lisp, for people with hair under their arms, using CAR and CDR and recursion. This program will print each number in the given list, with an axe emoji after each number (HN removed it, please insert an appropriate unicode emoji instead of the x):

  (defun lumberprint (n)
    (write n)
    (write-line "x"))
  
  (defun f (xs)
    (unless (null xs)
      (lumberprint (car xs))
      (f (cdr xs))))
  
  (defun main ()
    (f '(1 2 3)))
Save as "main.lsp" and run with "lisp main.lsp".

"unless" takes a condition and a list of statements. "null" checks if a list is empty. "write" outputs the given argument, but not a newline. "write-line" outputs the given argument and also a newline.

This should be enough to get you started. Then read SICP and draw the rest of the owl.

Best of luck!


For systems other than Arch, here are the wrapper scripts for SBCL that provides the `lisp` and `lispi` commands mentioned above.

lisp:

  #!/bin/sh
  #
  # SBCL wrapper script
  #
  filename="$1"
  mainfunction="${2:-main}"
  if [ -z $filename ]; then
    echo 'Please provide a filename as the first argument'
    exit 1
  fi
  if [ ! -f $filename ]; then
    echo "Could not find the file named \"$filename\""
    exit 1
  fi
  sbcl_path=$(which sbcl)
  if [ -z $sbcl_path ]; then
    echo 'sbcl is not in the PATH environment variable'
    exit 1
  fi
  if [ ! -x $sbcl_path ]; then
    echo "$sbcl_path is not executable"
    exit 1
  fi
  "$sbcl_path" \
    --noinform \
    --noprint \
    --no-userinit \
    --no-sysinit \
    --disable-debugger \
    --quit \
    --load "$filename" \
    --eval "($mainfunction)" \
    --end-toplevel-options
lispi:

  #!/bin/sh
  #
  # SBCL wrapper script
  #
  filename="$1"
  flag=""
  if [ ! -z $filename ]; then
    if [ ! -f $filename ]; then
      echo "Could not find $filename"
      exit 1
    fi
    flag="--load $filename"
  fi
  sbcl_path=$(which sbcl)
  if [ -z $sbcl_path ]; then
    echo 'sbcl is not in the PATH environment variable'
    exit 1
  fi
  if [ ! -x $sbcl_path ]; then
    echo "$sbcl_path is not executable"
    exit 1
  fi
  "$sbcl_path" --noinform $flag


(


(


If you want to learn C at the same time I can suggest "Build your own Lisp"

http://www.buildyourownlisp.com/


I remember wanting to learn lisp. I got stuck and reached out to the community for help.

And found them to be very hostile.

I decided I had better things to do with my time.


As a counter-anecdote (giving us anecdata), I did not have this issue when I got started. r/lisp and comp.lang.lisp were pretty welcoming. I don't do much on IRC, but my limited time there was productive and friendly.

There were (probably still are) a few assholes and zealots on comp.lang.lisp, but they were easy enough to ignore (killfiles are your friends). I think some people also got a bit testy and short there because of the trolls. People like Jon Harrop liked to go on there and basically say, "You're all morons and lisp is useless garbage here's why..." as a way of promoting F#. It was incredibly obnoxious, and I recall during his time as a troll there people becoming overly sensitive to other posts that looked like trolling but were meant in earnest. This would have been off-putting if you got caught in the crossfire.


I’m glad you had a better experience than I.

I tried learning CL back in 2006 and read a quickstart guide from the #lisp IRC channel. It had sentences in it like:

“ Using a plain text editor without any runtime connection to your Lisp implementation just because you think you prefer its keybindings is stupid and self-defeating.”

And

“Follow these directions or risk our wrath, or at least unsympathetic attitudes!”

The document, mercifully, doesn’t appear to exist any more. Maybe when I called them on it at the time they realized that maybe there’s a better way and changed it. But it definitely made a poor first impression.


I have been hanging out on IRC since 2006 too. The open source communities back then were indeed caustic. #python was an exception. #python used to be very nice to beginners. #c was perhaps the worst.

The attitude of these communities has changed a lot since then. It has been 14 years since then! Right now, #lisp and #emacs and their Reddit counterparts r/lisp and r/emacs are a very pleasant, friendly, and supportive community. For those looking to becoming a part of the Lisp or Emacs community, I strongly recommend giving #lisp, #emacs, r/lisp, and r/emacs a chance.


You could mention that it was almost 15 years ago in your previous post. That's more than enough time for the whole community attitudes to change, and they did.


Yeah. I think you were looking at it near the end of the "smug lisp weenie" era. Looking at some content from the early 00s does not give a favorable impression of the CL community or its attitudes. I came into it about the same time, but started paying attention to the community proper circa 2008. By then, I think the efforts to popularize the language and grow the community had tempered it quite a bit.


>And found them to be very hostile.

I started 4 years ago. They are very helpful and friendly.

Just approach them with a genuine interest.


Implement Lisp parser and a repl in your fav language. It's not difficult.

I made a series of videos how to do it in typescript. That was fun!

Here's the link if you're interested: https://youtube.com/playlist?list=PLP_fzAt_4T3QVlW_7Zr3CYLmV...




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: