For those thinking about learning CommonLisp...
Philosophic questions tend to receive good answers right here on Ward's wiki. Things like "is this possible in Lisp?", for instance. For specific technical questions such as "what piece of software would I use to do this?", it's best to look at the AluWiki.
How do we keep the source code files synchronized when doing incremental development? For example, if we're in a Lisp interpreter and we type in a few new function definitions, and play around with it it might be a while before we're happy with the code. How do we then get that new code into the source? I presume this is different from saving an image file. I hope the answer is something nicer than copy and paste into an editor running in parallel.
Typically you type your code directly into a source file in your Lisp-enabled editor. The development environments let you evaluate any individual expression in your source-files at any time, so it's still completely incremental. It's only "throw-away" code that you type directly into the shell - though copy&paste is always there on the occasions that you decide to keep some of it.
What are the most commonly used Lisp functions?
In my Lisp image, the five most commonly used of the standard Lisp functions are ERROR, FORMAT, APPEND, GENSYM, and WRITE-STRING. At least according to this not-quite-portable program:
(defun most-common-functions (&optional (n 5) (package :cl)) "Return the N most-referenced exported functions in PACKAGE." (let ((function-symbols '())) (do-external-symbols (symbol package) (when (regular-function-p symbol) (push symbol function-symbols))) (subseq (sort function-symbols #'> :key #'number-of-callers) 0 n))) (defun regular-function-p (symbol) "Return true if SYMBOL names a regular (non-special/macro) function." (and (fboundp symbol) (not (or (special-operator-p symbol) (macro-function symbol))))) (defun number-of-callers (function-name) "Return the number of functions that call FUNCTION-NAME. The result is cached on FUNCTION-NAME's NUMBER-OF-CALLERS property." (or (get function-name 'number-of-callers) (setf (get function-name 'number-of-callers) (length (function-callers function-name)))))(The answer is actually wrong, since the FUNCTION-CALLERS I'm calling out to isn't very accurate. But nevermind that!)
I'm thinking of writing a small program (say 1 day/weekend worth of effort) to learn Lisp. Any good suggestions?
Tic-Tac-Toe. Hmmm. Anything more inspiring? How about a Lisp interpreter? You guys scare me. [I think this may have been a bit of an inside joke (well, HaHaOnlySerious)... you can implement Lisp in Lisp very easily- in the trivial case you can do it in one line of of code: see MetaCircularEvaluator.]
Are there any online diaries of somebody coding in Lisp detailing what they were thinking about and the kinds of problems and solutions they had?
Not an online diary, but I ParadigmsOfArtificialIntelligenceProgramming sounds like just the ticket.
Is anyone doing XP in CommonLisp?
You mean, is anyone doing XpInCommonLisp?
Lisp people sometimes talk about incremental development, resuming execution after a bug fix etc., but it seems hard to find anything written about this. How do we do this with something like CLisp or CMUCL? Are there any good references or examples?
I doubt that most Lisp programmers use Emacs. I have never seen any numbers on that topic. I would believe that most Lisp programmers use an Emacs-like editor (which includes FRED, Zmacs, Hemlock, LispWorks's editor, ...).
And there's a project called Jabberwocky (c.f. http://jabberwocky.sourceforge.net/) which is writing a portable Lisp IDE in Java.
Why aren't they writing it in Lisp? Are there reasons that Lisp isn't suited to writing IDEs?
Well, there isn't really a good cross-platform GUI framework that's portable both across OS's and Common Lisp implementations. By writing the GUI foo in Java the Jabberwocky guys solve that problem.
Is there a reason there isn't a good cross-platform GUI framework for Lisp?
Yes: Lisp lost a lot of popularity in the late 80s, for reasons beyond the scope of this page (see AiWinter), so although there were a couple really nice GUI things for it on various Lisp Machines, the whole push to make things cross-platform came too late for Lisp to get a lot of money to that end.
Also, it's not clear that Lisp is all that much worse off than languages other than Java. There are Common Lisp bindings for most of the popular GUI toolkits from raw XLIB up to GTK and native widgets on Windows, OS X, etc. But unlike Java, there's no one vendor who's adopted the mission of trying to build a platform to compete with Microsoft.
If, however, one simply wanted to write cross-OS GUI apps in Lisp, the LispWorks product from Xanalys (http://www.lispworks.com) offers a GUI API (CAPI) that's supposed to be pretty good for WriteOnceRunAnywhere GUIs across Windows, the flavors of Unix they support and Mac OS X (I think--I know they support OsX but I'm not sure whether their GUI stuff works there.)
CAPI works on Mac OS X, too.
What does the S in S-Expression stand for?
Symbolic. See EssExpressions.
Does CommonLisp accept argument passing by name instead of position and default arguments (both in function calls and in closures)? Not a big issue, but a big curiosity.
Yes.
(defun f (x y &key thing (thang 123) (thong thang)) (list x y thing thang thong)) (f 1 2)===>(1 2 nil 123 123) (f 1 2 :thang 99)===>(1 2 nil 99 99) (defun f (x y &optional z (u (+ x y))) (list x y z u)) (f 1 2)===>(1 2 nil 3) (f 1 2 10) ===>(1 2 10 3) (f 1 2 10 20)===>(1 2 10 20)Also, there is a way to distinguish whether a keyword parameter was actually specified by the caller, or whether the default value was established. This is done by adding a third element to the keyword parameter specifier:
(defun f (x y &key (thang 123 thang-specified-p)) (when (eql thang 123) (if thang-specified-p (print "123 was specified explicitly") (print "123 came in as default value")))) (f 1 2 :thang 123) =output=> "123 was specified explicitly" (f 1 2)=output=> "123 came in as default value"
Is there a reason you can't specify how AssociationLists are implemented (hashtable, binary tree, etc.)?
That's sort of like asking why one can't specify how a hashtable is implemented, as an alist, binary tree, etc?) An alist is a particular data structure that happens to have similar (but not identical) semantics to hash tables.
That's not what I'm asking.
Now one might ask why there isn't a single unifying interface that provides different implementations, based on alists, hashtables, red-black trees, etc. No particular reason but there are perhaps enough differences between them that a unification isn't really that useful.
That's what I'm asking. Java has a Map interface and HashMap, TreeMap, etc. implementations. The AssociationList page makes it sound like a map, but says there is only one implementation and lookups are O(N).
Well, there's only one kind of alist but that's not the only data structure in Lisp that's capable of acting as a map. for instance hash tables are a first class data structure in CommonLisp, created with make-hash-table and come in four flavors depending on the kind of equality test you want to do. (Many specific Common Lisp implementations also provide a way for the user to define new flavors of hash tables that use a different equality-predicate/hash-function pair. This is, it's perhaps worth noting, different than Java where the equality/hashing is a function of the objects used as keys, not the HashMap itself.)
In fact, an alists is a bit of a funny creature since alists are not really first class objects. An alist is just a bunch of ConsCells arranged in a particular way and some functions that let you manipulate that structure conveniently. Now a ConsCell is a first class object (i.e. a given ConsCell has a unique object identity and there's a class). But an alist is just one of infinitely many ways of arranging ConsCells, albeit one that happens to have some support built into the language's standard library in the form of the aforementioned functions. Alists are useful in certain situations and are part of Lisp's history but are certainly not intended to be the be-all, end-all data structure for implementing maps. In general, where you would use a HashMap in Java you should use a hash table in CommonLisp. If you really need a red-black tree (what TreeMap is) you'll need to find or write one, since there isn't one built into the language or the standard library.
[This used to fit in somewhere] For instance, a hash table needs both a hash function and an equality predicate which are provided at instantiation time, while an alist only needs the equality predicate and it is passed in via the functions that use alists. Alists can also perform reverse lookups (via the function rassoc), just as efficiently as "normal" lookups. And alists can contain shadowed values: for a given key there can be multiple pairs in the alist at one time; because of the linear search the most recently added one will be found. It can later be removed, revealing the previously shadowed value. So, an interface which unified these would have strictly lesser power than either one.
So AssociationLists are more than maps. Is there a reason why this is a good thing?
And less. But to answer your question: No. On the other hand, there's no reason it's a particularly bad thing. Since Lisp is a dynamically typed language, there's less need to have everything implement some interface in order to say what you can do with it. Which is not to say that alists and hash tables are or were ever intended to be interchangeable. They serve different purposes. Which brings us to this older comment:
Of course, it would be easy to create your own classes and generic function protocol to provide just that interface; such a thing is probably not useful enough to be worth standardizing. One way or another, it's not standard.
I'm curious why a thing that looks so much like a map isn't a map.
Well, it is a map. It just happens not to have a common functional protocol with some of the other kinds of mapping data structures that exist in CommonLisp. And can't really, without pretty radically changing what it is.
Just by way of example, here's a sketch of a simple protocol for a "mapper" and two implementations, one built on top of an alist and another on top of a hash table. If you really wanted to have a unified view of these two data structures you could write your code in terms of the generic functions PUT and LOOKUP and make instances of ALIST-MAPPER and HASH-MAPPER as appropriate. Writing an implementation of RED-BLACK-TREE-MAPPER is left as an exercise for the reader. I don't, BTW, happen to think that this particular abstraction would be particularly useful; for the reasons explained above, if you don't pretty specifically want to be using an alist, with all it's quirks, you probably shouldn't be. But here's a code sketch:
(defclass mapper () ((impl :initarg :impl :accessor impl) (test :initarg :test :initform #'eql :reader test))) (defgeneric put (mapper key value) (:documentation "Put the given value into the mapper under the given key.")) (defgeneric lookup (mapper key) (:documentation "Get the value in the mapper under the given key or nil.")) ;;; alist based implementation of mapper (defclass alist-mapper (mapper) ((impl :initform ()))) (defmethod put ((mapper alist-mapper) key value) (let ((pair (assoc key (impl mapper) :test (test mapper)))) (if pair (setf (cdr pair) value) (cdr (push (cons key value) (impl mapper)))))) (defmethod lookup ((mapper alist-mapper) key) (let ((pair (assoc key (impl mapper) :test (test mapper)))) (if pair (values (cdr pair) t) (values nil nil)))) ;;; hash table based implementation of mapper (defclass hash-mapper (mapper) ()) (defmethod initialize-instance :after ((mapper hash-mapper) &rest (setf (impl mapper) (make-hash-table :test (test mapper)))) (defmethod put ((mapper hash-mapper) key value) (setf (gethash key (impl mapper)) value)) (defmethod lookup ((mapper hash-mapper) key) (gethash key (impl mapper)))