Search

1/09/2011

BATTLE OF THE LISPS: Common Lisp vs. Scheme

BATTLE OF THE LISPS: Common Lisp vs. Scheme

Scheme’s Idea

The way Scheme unified compared to the way CL differs vastly. Scheme’s idea of unification is exemplified by one of the first statements in the Scheme standard itself:
Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.

Essentially, Scheme was an attempt to take the core idea of Lisp, and derive a bare but practical “minimum” which could be reasonably extended as needed. This was highly successful, and the Scheme standard ended up being just over 50 or so pages (and anyone who has seen a language standard before would be staggered by such a low number). Due to the succinctness of the definition of the language, it is an incredible medium for studying programming languages and computer science in general (it is the language used in the famous book Structure and Interpretation of Computer Programs, or SICP).

The use of Scheme extends beyond simple educational or theoretical value. It is a practical language. The standard includes many examples of practical use. Since Scheme is a lisp, it can be extended to the users’ needs via macros and such. So, while being incredibly simple and small, it does not preclude it from being useful or practical.

CL’s Idea

CL took an entirely different approach. Instead of making a language as a result of picking out fundamentals of earlier languages and ideas, it, in a sense, took many of the previous popular lisps (notably MacLisp, not related to Apple’s Macintosh), and took the good, tested, and popular features from them. A central goal in the design of CL was to make a language that was highly compatible (in terms of features and how things worked) with other lisps. If four out of five lisps had a certain way of doing hash tables, then CL would likely have this feature as well.

As a result, CL ended up being a very large language with the genes of previous lisps highly woven in. The language standard is 1153 pages of printed text (though just about every function described has examples and whatnot). Some people see CL as having an incredible amount of cruft and baggage, others see the extra features (that could otherwise be there with libraries) as means of keeping code consistent and portable.

As one might guess, CL is not a great language for using as a model for studying. But if one is programming to get things done, then it of course is great and practical.

Names



SchemeCommon LispMeaning
mapmapcarApply a function to every element of a list.
definedefun, defparameter, defvarDefine a function (or value).
beginprognExecute a block of “statements” (à la Pascal).
newlineterpriPrint a newline.
set-car!rplacaDestructively set the car of a pair.
pair?conspDetermine if a value is a pair.
string->numberparse-integerConvert a string literal like "123" to a number (integer).

The “informality” and brevity of CL’s choice of many names seems to be a turn-off to many. As it turns out, however, the names of many CL functions are the way they are for a reason. If something is a definitional form, it will almost always begin with def (defun, defmacro, defparameter, defconstant, …). If something is destructive or non-consing, it will likely begin with the letter n (nconc, nreverse, nsubst, …). In contrast, Scheme uses ! to denote destructive operations (set!, reverse!, concatenate!, …).

On a similar note, CL tends to end a function with p if it is a predicate of some sort (characterp, evenp, …) whereas Scheme uses a ? to denote such (char?, even?, …).

Functions and Values
Both languages allow for first class functions. However, in Scheme, functions are “truly” first class in that they have no special treatment. A parameter to a function may also be a function, may be listed, may be called, etc. In CL however, things are different. While function parameters may themselves be functions, they must be used in a different way.

In CL, every symbol may have a function definition, and “value” definition. So one symbol may actually represent several different data.

CL is often called a “Lisp-2″ because it has two primary namespaces for values to exist. Scheme is called a “Lisp-1″ because all values co-exist in a single namespace. In reality, we might actually say CL is a “Lisp-n”, because we actually can have more namespaces, such as for dynamic variables.

Implementations
Everyone and their dog has their own Scheme implementation.


I highly recommend two Schemes: Chicken Scheme for your compiling and interpreting needs (also has a great library system and code repository system), and Chibi Scheme, a standards-strict tiny Scheme suitable for embedding in C applications. There are other good Schemes, but those are what I like most.

The CL implementations are generally known to be standards conforming and usually produce good code. My two favorites are SBCL for general work and very efficient compilation, and CLISP as a very portable system (as it uses its own bytecodes and VM). A nice thing about extensions to the CL language is that they can be delimited in their own namespace (using CL’s packages). In SBCL for example, extensions are in the SB-EXT package.

沒有留言: