Nikodemus' Common Lisp FAQ ========================== Last updated: 2013-01-27 This is a highly uncanonical Common Lisp FAQ with a strong editorial bias, by Nikodemus Siivola. Partially based on various comp.lang.lisp and general Lisp FAQs. If you think I've stolen your words I'm all to happy to 'fess up, so feel free to drop a line to . Current version of this FAQ is available from: http://random-state.net/files/nikodemus-cl-faq.txt http://random-state.net/files/nikodemus-cl-faq.html This FAQ is also posted to comp.lang.lisp every once in a looong while. * Just Starting Out ** Common Lisp? CL? Clisp? Lisp? `Common Lisp' is the name of the ANSI standardized language this FAQ is about. `CL' is the preferred abbreviation of that name. `Clisp' is not an acceptable abbreviation, as it is the name of a specific Common Lisp implementation. `Lisp' is a category of languages to which CL belongs. Is hasn't been written as LISP for the last 20 years or so. Common Lisp is often referred to as just Lisp when the context is clear. ** Why should I care about Common Lisp? You can read about the features of Common Lisp here: http://random-state.net/features-of-common-lisp.html If that doesn't make you care, I can't help you. ** So is Common Lisp the best language? There isn't such a thing as "the best language". I find it a very good language for many many purposes. Some people find it a decent language for some purposes. Some people don't like it at all, but they don't know what they're missing. ** How can I learn Common Lisp? 1. Read a good book on Common Lisp. 2. Start using it. Many people seem to manage the first stage over and over again, but fail to act on the second one. Seriously: you cannot learn any programming language without using it, nor can you properly understand one without working on a moderately large program in it. ** Are there any common pitfalls I should avoid? Any good book will more than adequately deal with language-level gotchas, but there a couple of psychological and social pitfalls that stumble some people: 1. Learning about Lisp macros makes some people go nuts. While Lisp macros are the bee's knees, the power that goes with them sometimes makes newcomers lose all perspective. A typical symptom is trying to build something without having a clear idea of what it is supposed to do. Remember that anything you can write with a macro you can write without one. Sometimes it may not be practical to do so, but remembering this will help keep you grounded. Learn to walk before you try to run. It doesn't take long, is well worth it -- and then you get to fly. 2. Don't be shocked when Lisp isn't perfect. This is not news. Some people come to Lisp over-hyped, and are disappointed when it falls short of their expectations. Other people compare Lisp to language X and find it falls short somehow. Both of these can be fair and accurate judgments, but trouble starts when people head to eg. #lisp to air these issues. If the assessments are accurate, then most likely the subject has been discussed to death several times over the years, and no-one has much patience for it. If the assessments aren't accurate, or are considered more theoretical than practical, then nonetheless most likely several disgruntled newbies have aired the exact same complaints several times over the years and no-one has any patience for it. This is not to say you aren't allowed to say un-nice things about Lisp on the internet, but ... if you come in as a newbie telling people how bad things are, don't expect people to welcome you with open arms -- even if your complaints are 100% accurate. Complaints coming from people who have been around for a while and who provide positive inputs to the community carry a lot more weight. 3. Experienced lispers active on the internet see a lot of trolls. `A LOT OF TROLLS.' A confused newbie can sometimes look like a troll, in particular because some of most notorious recurring trolls habitually masquerade as being new to Lisp. So people may think you're a troll and respond accordingly. Best way to avoid this: be polite. If you're told you're confused or mistaken, assume for the moment that they're either right, or that you at least very much look like so. ** Which book should I read first? Read Peter Seibel's `Practical Common Lisp', a.k.a. PCL. It is a good starting place if you already know how to program in some other language. It's available both online and in print: http://www.gigamonkeys.com/book/ Another alternative is David Touretzky's `Common Lisp: A Gentle Introduction to Symbolic Computation', which is a good choice if you are new to programming or find PCL too hard. Even if you start with this, read PCL afterwards. If you've already read PCL and understood it, you can safely skip this. Available both online and in print: http://www.cs.cmu.edu/~dst/LispBook/index.html There are plenty of other books too, but these two are the best bets for starters. Land of Lisp isn't bad, but in my limited experience it can foster some misconceptions. If you start with it, follow up with PCL. I do not recommend starting with Paul Graham's books: they're not really up to date and do not foster good style in my opinion. You should familiarize yourself with the `Hyperspec', aka CLHS -- the online version of the language standard, which is an invaluable reference: http://www.lispworks.com/documentation/HyperSpec/index.html Don't try to read it right now. Just remember it is there, and contains the authoritative answer to all possible questions about CL: it is the perfect place to check if you find yourself in doubt about what a given operator does. It is also the place you should look in to discover if there is a built-in that already does what you need. Also, do not neglect the documentation that comes with your implementation. In case of SBCL, the manual is at: http://www.sbcl.org/manual ** Which implementation should I pick? Depends on your needs, but as long as you are just starting out it really doesn't matter. However, if you are expecting a particular group of people to help you, do pick an implementation they are familiar with. Once you have learned more you can make an informed decision for yourself. Moving between implementations is not that big an issue, really, so there is no point in agonizing over initial choice. That said, I am highly partial to SBCL: http://www.sbcl.org/ SBCL is open source, runs on a number of platforms (including Windows), has a good native compiler, takes ANSI compliance pretty seriously, and generally bring happiness and joy to the world. ...but then I would say that, since I am one of its developers. If SBCL doesn't bake your cake for one reason or another, I would suggest working your way down the following lists: Open source: Clozure CL ABCL ECL Clisp Commercial: Lispworks Allegro CL Scieneer ** Where are all the libraries? Is there a CPAN or RubyGems equivalent? `QuickLisp' is akin to RubyGems: http://www.quicklisp.org/ It puts a ton of libraries at your fingertips, and manages dependencies between them. You really, really want to use QuickLisp. Closest things to CPAN are `Cliki' and `common-lisp.net': http://www.cliki.net/ http://www.common-lisp.net/ ...but they're nothing like it, really. Worth a visit, though. ** Which IDE should I use? If you are using SBCL, then you want to use Emacs and Slime: http://www.common-lisp.net/project/slime/ Even if you haven't used Emacs before, do yourself a favor and use Slime -- the learning curve isn't all that long, and you can get at all the commands from menus too. You can install Slime through Quicklisp, see ``How do I set up my environment?'' below. M-x slime-cheat-sheet should help you get started -- but it only shows a small sampling of Slime's capabilities. If you are using another implementation, use the IDE the implementors recommend for it (though Slime works with practically every implementation). For a reasonable Lisp experience your editing environment should at least: * Autoindent lisp correctly. * Match parens. * Provide commands like: Edit Definition, Compile Defun, Eval Expression, Describe Symbol, Disassemble Function, Trace Function, Inspect expression, etc. for interacting with your Lisp. * Provide integration with the debugger. * Provide integration with the inspector. Slime does all this and more. If you love Vi(m), then you may want to check out Slimv, which hooks Vim into the Common Lisp part of Slime: http://www.vim.org/scripts/script.php?script_id=2531 https://bitbucket.org/kovisoft/slimv/ http://kovisoft.bitbucket.org/tutorial.html ...but I cannot vouch for it, as I don't use it. ** How do I set up my environment? This is, at the time of writing, an up-to date guide for getting SBCL, Slime, and Quicklisp set up: http://mohiji.nfshost.com/2011/01/modern-common-lisp-on-linux/ http://mohiji.nfshost.com/2011/01/modern-common-lisp-on-osx/ Directions for Windows reference Clisp, but you can't have everything... http://mohiji.nfshost.com/2011/01/modern-common-lisp-on-windows/ ** Is there a GUI? Yes and no. There is no single GUI that everyone doing GUI stuff is using. Commercial implementations tend to come with GUI libraries that their proponents seem quite fond of. However, they are not portable across different Common Lisp implementations. If you use a commercial implementation and don't need such portability then the vendor toolkit is a natural choice. Depending on implementation, they may actually provide portability across operating systems, which may or may not be enough for your needs. On the open source side, there are several libraries you can use. CommonQt is a Common Lisp binding to the smoke library for Qt: http://common-lisp.net/project/commonqt/ LTK is built on top of Tk: http://www.peter-herth.de/ltk/ CL-GTK2 and CLG both provide GTK+ bindings, but I'm not sure what their current status is. GTK Server may also be worth a look: http://common-lisp.net/project/cl-gtk2/ http://sourceforge.net/projects/clg/ http://www.gtk-server.org/ CLIM (Common Lisp Interface Manager) is a semi-standardized GUI API specification, quite different from the widget & event-loop based GUIs listed above. Don't expect it to feel familiar immediately. http://random-state.net/files/how-is-clim-different.html Some people swear it is the best thing since sliced bread, and some people think sliced bread is better for building GUIs then it is. At any rate, most commercial implementations provide a CLIM implementation, and there exists a portable open source implementation called McCLIM, which is quite usable, but has lately stalled a bit. http://common-lisp.net/project/mcclim/ CLX is a portable low-level X11 interface written in Lisp, providing a level of abstraction similar to Xlib. http://www.cliki.net/CLX https://github.com/sharplispers/clx While not strictly speaking a GUI, I would be remiss if I didn't mention CL-OPENGL: a portable binding to the OpenGL, GLU and GLUT APIs: http://common-lisp.net/project/cl-opengl/ ** What online forums are there? Not a forum per se, but Planet Lisp is a blog aggregator of various Common Lisp blogs. There's just enough traffic to keep it interesting without being overwhelming: http://planet.lisp.org/ LispForum is an honest-to-goodness forum: http://www.lispforum.com/ but I can't vouch for it, since I've never been a regular. Then there's comp.lang.lisp on Usenet / Google Groups, but it is inhabited by several trolls. While many of the frequent writers are quite knowledgeable, uninformed speculation remains common. Reading it can be a stress-inducing experience, and is definitely not necessary in order to use Lisp. http://groups.google.com/group/comp.lang.lisp There are several special-purpose mailing lists which have vastly better signal to noise ratio: all implementations tend to have their own user- or help-lists, and most libraries have their own mailing lists. Eg. for SBCL: https://lists.sourceforge.net/lists/listinfo/sbcl-help The IRC channel #lisp on freenode.org is quite popular also, especially among the open source users and developers. Be aware that #lisp is fairly strict about staying on-topic, and the topic is Common Lisp, not lisp-in-general. #lispcafe is another freenode.org channel, with a more relaxed attitude. There is also a fairly active game writing community, but I'm not really familiar with it. Googling for lispgames should set you on its trail. Mailing list pro is targeted at people who actually use Common Lisp on a regular basis. Discussions about other Lisp dialects are off-topic, and newbie-questions are NOT welcome: http://lists.common-lisp.net/mailman/listinfo/pro * Language Features ** How do I compile a file? Short answer: start your Lisp, and type: (compile-file "/path/to/myfile.lisp") Then you probably want to LOAD the compiled file. Long answer: most compiled languages are non-interactive -- you compile a file from the command line or IDE, and then run the compiled file. Not so with Lisp. While you can generally speaking turn your project into an executable file, the typical Common Lisp development session does not resemble the edit, compile, run cycle you've come to expect. Normally you interact with a long-running Lisp process that holds your development session, and add code to it incrementally. For example: 1. Open Emacs, start Slime and Lisp with M-x slime. 2. Load existing code to Lisp using eg. ASDF. 3. Open the file you're interested in, edit a function, and then hit C-c C-c to recompile that single function. 4. Go to the Slime REPL and test your changes. 5. Go to step 3. The ASDF alluded above is "Another System Definition Facility", which can be used to describe the way several files form a single system, and allows the files to be eg. compiled and loaded with a single command. Sort of like Make, but not at all like it really. ** How do I make an executable? The answer depends on the implementation you are using. Refer to its documentation. That said, if you are using SBCL: ;; First load your application into SBCL, then do this. MY-FUNCTION ;; is the entry point to your application. (save-lisp-and-die "my.exe" :executable t :toplevel 'my-function) ** FUNCALL and APPLY -- what's the difference, which one should I use? Short answer: Use FUNCALL if you can, APPLY otherwise. Long answer: With FUNCALL the number of arguments must be known at the call site. With APPLY (and MULTIPLE-VALUE-CALL) the number of arguments need not be known. (defun map-list-with-1 (function list arg) (mapcar (lambda (elt) (funcall function elt arg)) list)) (defun map-list-with-n (function list &rest args) (mapcar (lambda (elt) (apply function elt args)) list)) There is no reason to write MAP-LIST-WITH-1 using APPLY, and FUNCALL is almost certain to be more efficient here. In contrast, MAP-LIST-WITH-N cannot be written using FUNCALL, as the number of arguments is not known at the call site -- APPLY has to be used. ** SET, SETQ and SETF -- what's the difference, which one should I use? Short answer: Always use SETF. Long answer: Originally, in the days of yore, long before there was Common Lisp, there were no lexical variables -- only dynamic ones. And there was no SETQ or SETF, just the SET function. What is now written as: (setf (symbol-value '*foo*) 42) was written as: (set (quote *foo*) 42) which was eventually abbreviated to SETQ (SET Quoted): (setq *foo* 42) Then lexical variables happened, and SETQ came to be used for assignment to them too -- so it was no longer a simple wrapper around SET. Later, someone invented SETF (SET Field) as a generic way of assigning values to data structures, to mirror the l-values of other languages: x.car := 42; would be written as (setf (car x) 42) For symmetry and generality, SETF also provided the functionality of SETQ. At this point it would have been correct to say that SETQ was a low-level primitive, and SETF a high-level operation. Then symbol macros happened. So that symbol macros could work transparently, it was realized that SETQ would have to act like SETF if the "variable" being assigned to was really a symbol macro: (defvar *hidden* (cons 42 42)) (define-symbol-macro foo (car *hidden*)) foo => 42 (setq foo 13) foo => 13 *hidden* => (13 . 42) So we arrive in the present day: SET and SETQ are atrophied remains of older dialects, and will probably be booted from eventual successors of Common Lisp. Always use SETF. ** '(1 2 3) or (list 1 2 3)? Short answer: Use (list 1 2 3) unless you understand the difference. If you have '(1 2 3) to deal with, don't modify it destructively. (Eg. with SORT or NREVERSE.) Long answer: First off, the single quote is a read macro, transforming 'anything into (quote anything) at read-time, so '(1 2 3) === (quote (1 2 3)) Secondly, QUOTE is a special operator that returns its argument unevaluated. So, '(1 2 3) returns a literal list. Like in most languages, modifying literal data leads to undefined consequences. For example, the compiler is allowed to coalesce constants including literals: (let ((a '(1 2 3)) (b '(1 2 3))) (eq a b)) ; => T or NIL The upshot of which is that modifying A may also modify B. What is QUOTE good for, then? If you have eg. large constant lists that you would like the compiler to coalesce, then putting them in as literal constants gives the compiler license to do so. ** What's with the *EARMUFFS*? Whenever you use either DEFVAR or DEFPARAMETER to define a variable, always name it *LIKE-THIS*. You never use them for local variables. (defvar *this-is-good* ...) (defvar this-is-very-wrong ...) Why? If you don't yet know what special variables are, keep reading the book you're using and come back here when you do -- and in the meanwhile use the earmuffs. There are two basic errors that are really easy to make that earmuffs protect against. *** Case 1: Binding a special variable by accident. (defparameter foo "foo!") (defun say-it () (write-line foo)) (defun say-more (foo) (say-it) (format t "now say ~A~%" foo)) Now (say-more "bar!") will print out say bar! now say bar! instead of the intended say foo! now say bar! ...oops. *** Case 2: A typo causing you to read a special instead of a local -- but there's no warning. Normally you get a compile-time warning and a run-time error for (defun foo (bar) bat) but if you've previously done (defparameter bat "baseball") then you don't get either, and will waste time debugging, trying to figure out where things go wrong. If your code is for your personal enjoyment no-one cares if you use earmuffs or not, but when you post code or publish it, not marking *SPECIAL* variables special will waste other people's time. Please don't do that! You don't waste other people's time just if your code has a bug: whenever I see (defparameter no-earmuffs ...) I realize I need to read the code extra-carefully because there's no guarantee that code that looks innocent at a glance will not have non-local side-effects or dependencies. Always use the earmuffs. It's true that when you understand the rules you can break them, but for this one it is really rare to find a real exception. -- Happy Hacking, -- Nikodemus