Some of these features include: packages, arrays, structures, hash tables, object-oriented programming features, a powerful macro feature for extending the language, generalized assignment, and much more.
Common Lisp, by contracts, requires every implementation to support floating point numbers, rational numbers, integers of arbitrary precision, complex floating point number, and complex rational numbers. This fact makes programs that use numbers more portable.
No such rule exists in Common Lisp, although many Common Lisp compilers actually do optimize tail calls. It is therefore less frequent in Common Lisp to use tail recursion for (say) traversing lists. Instead, Common Lisp has a rich set of iteration primitives for exactly that purpose.
For instance, in Scheme, there is a difference between:
(define (f x y . (z)) ...)which is syntactically illegal, and:
(define (f x y z) ...)which syntactically legal. As data (if read by the read function) they are the same. Thus, Scheme does not require code to be read by the read function.
Common Lisp, on the other hand, does require two such forms to be equivalent. This feature is the very basis of the Common Lisp macro system, which uses Lisp data to represent and manipulate Lisp code.
Since no such equivalence exists in Scheme, one can argue that it is impossible to ever have a good macro system for Scheme. In practice, of course, nearly all implementations do define the equivalence and do contain macro systems.
The main idea in Common Lisp is that the name fun in an expression such as:
(fun arg)is treated differently from the name arg, simply because it is the first subexpression of a function call. Instead of using the normal value of the variable fun, its function value is used. In normal circumstances, this works the same as Scheme. However, as soon as something slightly more complicated is attempted, the difference is visible.
Perhaps the most obvious difference is that in Common Lisp, it is possible to use the name of a function as an ordinary value without shadowing the function. This is possible in Common Lisp, but not in Scheme:
(let ((list '(1 2 3))) (list list))In the expression (list list), the first occurrence of list refers to the built-in function of that name, and the second refers to the local variable created by let.
On the other hand, this is possible in Scheme but not in Common Lisp:
(let ((fun (compute-a-function))) (fun x y))Here, Common Lisp will search for a global function definition of fun (which probably does not exist), whereas in Scheme, the value of the local variable will be used. To do the same thing in Common Lisp, we need to use a built-in function called funcall like this:
(let ((fun (compute-a-function))) (funcall fun x y))Now, the name fun is in an argument position, so the value of the local variable is used and passed to funcall. The built-in function funcall then applies its first argument (as a function) to the rest, which is what was intended.
We have seen how Common Lisp through the built-in function funcall is able to call a function that is the value of an ordinary variable. We must also solve the inverse problem, i.e., obtain the function object that is not the value of an ordinary variable, but only the global function value of some name such as car.
This is possible in Scheme:
(map car l)but not in Common Lisp, since typically, the variable car would not have an ordinary value. The solution is a special form called function, but usually abbreviated #'. Here is how to write the same thing in Common Lisp (also taking into account the fact that the Scheme function map is called mapcar in Common Lisp):
(mapcar #'car l)
(define (f l) (g (reverse l)))whereas in Common Lisp, you would use the defun special form with slightly different syntax:
(defun f (l) (g (reverse l)))Other differences exist, like set! in Scheme and setq in Common Lisp, and map in Scheme which does not correspond to the Common Lisp function with the same name, but instead to the Common Lisp function mapcar