(CL) are about as similar as Java and C++.
The following compares the standards for both languages.
Many implementations offer extensions.
- has more built-in procedures and macros, including some moderately deep ones like GET-SETF-EXPANSION
- has more built-in types (like multi-dimensional arrays)
- has a standard facility for creating new types
- has a standard package system
- has a standard object system (CLOS, the CommonLispObjectSystem)
- has a standard exception-handling system (aka "condition system")
- has macros that allow arbitrary Lisp code to transform code
- has symbol macros (DEFINE-SYMBOL-MACRO, SYMBOL-MACROLET)
- has compiler macros for user-defined optimizations (DEFINE-COMPILER-MACRO)
- has symbol property lists.
- has hash tables.
- has dynamically scoped variables (a.k.a. SpecialVariables) which are extremely useful.
- has a working UNWIND-PROTECT
- is a very large language, with both the positive and negative implications.
- has a FORMAT function, which is something like C's printf but type safe and much more powerful
- has a big streams library, including string streams which do I/O to and from strings.
- has a sequence library for manipulating vectors and lists in useful ways.
- has a customizable read syntax by manipulation of read tables
- has the COMPILE function to dynamically compile source code to functions.
- has functions to compile source files and load them.
- provides mechanisms to control whether evaluation happens at various "times" like compile time, load time or execution time.
- defines evaluation order and specifies the result value for all, or nearly all built-in functions and operators.
- allows car and cdr on the empty list without signaling an error
- has built-in support for multiple values
- has built-in support for complex function parameter lists (&rest, &optional, &key)
- has built-in support for various forms of declarations (type, optimizations, dynamic extent, ...)
- has built-in support for reading and writing sequences from streams
- treats t and other values as "true" and NIL as "false"
- has a fairly minimal set of built-in procedures
- has CallWithCurrentContinuation (which lets you express some amazing stuff but which also makes it tricky to express UNWIND-PROTECT)
- has a hygienic, referentially transparent macro system based on rewrite rules (DefineSyntax), but most SchemeImplementations have one or more additional macro systems more like the CL one (some of them clones), since some things are tricky to express in standard scheme macros.
- many schemers believe it has cleaner semantics, particularly a single namespace and consistent use of lexical scoping (but see HyperStaticGlobalEnvironment)
- evaluates the function position of a function call the same way as the argument positions
- requires support for TailCallOptimization
- is a small language, with both the positive and negative implications.
- many standard forms in Scheme have an undefined result value, and the order of function argument evaluation is unspecified.
- doesn't use the same value for failure, falsity and the empty list.
- is a SingleNamespaceLisp.
, Lieven, EdwardKiser
(Please stop SHOUTING -- NoelWelsh
They aren't shouting - in Lisp and Scheme symbol names are generally referred to in uppercase letters. -- BillAtkins?
Moved from IwannaLearnLisp:
''There are three fundamental technical differences between Scheme and Lisp that go deeper than just Scheme being a small clean dialect of Lisp:
- (1) Scheme implementations are required to optimize tail calls (turn function-call followed by return into a jump to the new function - this is usually called TailRecursionElimination), which is more than a speed issue; it means that tail recursive functions require a bounded rather than unbounded amount of stack.
- (2) Common Lisp has a different namespace for functions than for other variables (equivalently you could say that any given symbol could have a regular value as well as a function value simultaneously). This means that in Common Lisp, to refer to a function by name in a position where Lisp expects a variable name, we must use the FUNCTION special operator, normally written #' [SharpQuote], to get the function named by the symbol rather than the value of the variable. This means that higher order functions are slightly cleaner in Scheme. And
- (3) Scheme stresses a continuations model of computation. -- DougMerritt, clarification by -- PeterSeibel''
Btw., one should make sure what you mean when you say Lisp. Lisp the family of programming languages (Common Lisp, Scheme, ISLisp, EuLisp?
, XLisp, AutoLisp
, ...) or Common Lisp. There are other Lisp dialects that also only have a single namespace.
In looking for information about the difference between Lisp and Scheme, I just found the Lisp FAQ (http://www.faqs.org/faqs/lisp-faq/
) which seems interesting. For the record, it says (as the answer to q1-1):
- What is the difference between Scheme and Common Lisp?
- Scheme is a dialect of Lisp that stresses conceptual elegance and simplicity. It is specified in R4RS and IEEE standard P1178. (See the Scheme FAQ for details on standards for Scheme.) Scheme is much smaller than Common Lisp; the specification is about 50 pages, compared to Common Lisp's 1300 page draft standard. (See question [4-10] for details on standards for Common Lisp.) Advocates of Scheme often find it amusing that the Scheme standard is shorter than the index to CLtL2.
- Scheme is often used in computer science curricula and programming language research, due to its ability to represent many programming abstractions with its simple primitives. Common Lisp is often used for real world programming because of its large library of utility functions, a standard object-oriented programming facility (CLOS), and a sophisticated condition handling system.
This note may belong on another page here but it seems useful for the moment within the scope of my desire to learn Lisp. Do people here have a preference between these two, perhaps for reasons of style or utility, and if so, why? (Again, maybe worth refactoring off into somewhere else when discussion is done.) -- EarleMartin
''Common Lisp is about as large as a Scheme with a Common-Lisp-like library plus some Common-Lisp-like language extensions (Common Lisp Object System for example). The difference is that Common Lisp has standardized on much of the useful stuff and tried to define it that programmers know how to use it portably between different platforms (different Lisp implementations and different operating systems). Additionally typical Common Lisp implementations provide quite a few extensions to Common Lisp (CLOS-based streams/conditions/..., networking, database access, additional character sets, GUI toolkits, threads, ...).
The Scheme community now defines a lot of extensions to Scheme (SRFI, http://srfi.schemers.org/
Unfortunately Scheme and Common Lisp are like two siblings who are both very similar and very different. Thus they (or their proponents) fight a lot. The main difference is in the way the two language's standards work--Common Lisp's standard is big and standardizes a lot of things. This makes it hard to implement and hard to absorb all of. (Though there's plenty you can do before you learn the whole thing--it's mostly library functions so the worst that will happen if you don't know some part of the standard is you'll reimplement some built in functionality.) The Scheme standard on the other hand is quite small and kept that way on purpose. This makes it easy to implement Scheme qua Scheme. But then to make a Scheme into an actually useful language, each implementation has to add in many of the things that are standardized in Common Lisp. Which means any one Scheme implementation is likely to have many, if not most, of the features that all Common Lisps have but in an implementation dependent way. Beyond those issues there are deeper philosophical and techno/religio issues separating the languages.
(Shameless plug: I'm currently working on a book about CommonLisp
for Apress which is targeted at people who, like Earle, have heard enough about Lisp to want to learn something about it and who are coming from a Perl, Java, Python, or C background. If you are interested in taking a look at some early chapters they are up on the web (for now) at http://www.gigamonkeys.com/book/
and I'd love to hear any feedback folks have.) -- PeterSeibel
Looks very nice! I'll look at it in more detail and possibly drop you some comments. -- PanuKalliokoski
So, there are differences between Scheme the standard (R5RS) and Common Lisp the standard (ANSI Common Lisp).
Fortunately in reality we don't develop software with standards, but with implementations. Especially since both standards barely define enough to write a useful program (no networking, no threads, no foreign function interfaces, no GUI libs are defined in these standards...).
I disagree; you can do a heck of a lot of useful computation without platform hooks. Common Lisp gives you a lot of functionality to write the computational core of an application in a portable way.
"- A computational core? Without threads? Without memory management? Without useful access to files? ..." CL has memory management (obviously) and streams for file access. Threads are not standard, but then they are not essential for computation, but rather for optimizing an application for real-time responsiveness or multiprocessor use.
- - - good joke. Where does have CL (we are talking about the STANDARD -> ANSI CL) memory management? All you can do is create objects. The standard says nothing about GC and related topics. It does not even mention it. - Streams for file access? Sure. Try to open a file. The ANSI CL standard says you can use a string to name a file. Some operating systems have Unicode coded filenames. ANSI Common Lisp does not have Unicode strings. So you possibly can't access a lot of files with standard ANSI CL. Implementations have to provide solutions to this: e.g. to provide Unicode strings and to allow OPEN and WITH-OPEN-FILE to accept Unicode strings as filenames. - Right, threads are not essential. Wrong, they don't have anything to do with real-time responsiveness and not much with multiprocessor use. All commercial and many free CL implementations are providing some kind of threads - often based on the initial Lisp machine model. Some CL-based Webservers
are using them. Many GUI toolkits are using them. Many development environments are using them. Still there is no standard. People are interested in this topic. CLIM-SYS provides a core version of threads.
Now compare the usual SchemeImplementations
(MIT Scheme, Chez Scheme, Bigloo, DrScheme
, ...) + the usual Scheme extensions (e.g. those provided by SchemeRequestsForImplementation
) with Common Lisp implementations (CMU CL, GCL, CLisp, SBCL, OpenMCL, MCL, LispWorks
, ACL, ECLS, Corman CL, Genera, ...) + the usual Common Lisp extensions.
You will see that Scheme implementations can be BIG (like MIT Scheme), they often have procedural macros, support DynamicScoping
(FLUID-LET), have OO-extensions and so on. That means that any (what? one is the same as any?) larger Scheme implementation starts to look like any other large Common Lisp implementation (name that law ;-). GreenspunsTenthRuleOfProgramming
The big difference is that a larger proportion of that large Common Lisp implementation is standardized, that is all. Whereas only a tiny proportion of that large Scheme implementation has anything to do with the fifty-odd pages of the Scheme report, plus SRFI's.
On the other hand you will find many Common Lisp implementations that will support some form of tail call elimination.
Also see TheEvolutionOfLisp
provides powerful iteration operations (e.g. the LOOP macro). Scheme encourages/enforces iteration-as-recursion: it has added syntactical support for iteration (e.g. the DO looping construct), but what looks like iteration is really recursion. It is more a philosophical difference: CommonLisp
asserts that iteration operators are a good thing. Scheme asserts that iteration-as-recursion is a good thing (while allowing that iteration operations are handy sometime). Also see RecursionVsLoop
I'm not sure what "what looks like iteration is really recursion" means. A scheme named-let loop is equivalent to a recursive call, but in the usual case the recursive call is a tail call and is effectively reduced to a jump. If this is what the distinction between "iteration" and "recursion" is aiming and, then scheme loops are generally "iterative".
makes a distinction between "recursive process" and "recursive procedure". I believe this is gratuitously confusing to the newbie, but this presumably helps understand what Schemers think when they use the terms "iteration" and "recursion".
As someone who would definitely be considered an amateur programmer, I found the distinction between a "recursive process" and a "recursive procedure" to be very useful. Just because a procedure calls itself (making the procedure recursive) doesn't mean it cannot be performing its job by basing calculations off of a counter (therefore making the process iterative, not recursive, despite being done in a recursive procedure). Makes sense to me, and I'm a liberal arts student.
Of course, Lisp and Scheme are completely different worlds.
Scheme uses LexicalScoping
normally, and provides DynamicScoping
for variables declared as special
There are several existing scheme and lisp implementations that are designed to be embedded into an application - Guile, Librep, DrScheme
, Chibi Scheme, etc. Discussion on embedding Scheme on Palm Pilot moved to EmbeddingSchemeOnPalm
[section moved to IsSchemeLisp
It is probably equally difficult to go both ways. I don't think it is a good idea
to start in Scheme if you really want to learn CL. Neither is the opposite.
A SHORT BALLAD DEDICATED TO THE GROWTH OF PROGRAMS
This is a tale of a sorry quest
To master pure code at the T guru's behest
I enrolled in a class that appealing did seem
For it promised to teach fine things like T3 and Scheme
The first day went fine; we learned of cells
And symbols and lists and functions as well
Lisp I had mastered and excited was I
For to master T3 my hackstincts did cry
I sailed through the first week with no problems at all
And I even said "closure" instead of "function call"
Then said the master that ready were we
To start real hacking instead of simple theory
Will you, said he, write me a function please
That in lists would associate values with keys
I went home and turned on my trusty Apollo
And wrote a function whose definition follows:
(cdr (assq key a-list))
A one-liner I thought, fool that I was
Just two simple calls without a COND clause
But when I tried this function to run
CDR didn't think that NIL was much fun
So I tried again like the good King of yore
And of code I easily generated some more:
(cond ((assq key a-list) => cdr))
It got longer but purer, and it wasn't too bad
But then COND ran out and that was quite sad
Well, that isn't hard to fix, I was told
Just write some more code, my son, be bold
Being young, not even a moment did I pause
I stifled my instincts and added a clause
(cond ((assq key a-list) => cdr)
Sometimes this worked and sometimes it broke
I debugged and prayed and even had a stroke
Many a guru tried valiantly to help
But undefined datums their efforts did squelch.
I returneth once more to the great sage of T
For no way out of the dilemma I could see
He said it was easy -- more lines must I fill
with code, for FALSE was no longer NIL.
(let ((val (assq key a-list)))
(cond (val (cdr val))
You'd think by now I might be nearing the end
Of my ballad which seems bad things to portend
You'd think that we could all go home scot-free
But COND eschewed VAL; it wanted #T
So I went back to the master and appealed once again
I said, pardon me, but now I'm really insane
He said, no you're not really going out of your head
Instead of just VAL, you must use NOT NULL instead
(let ((val (assq key a-list)))
(cond ((not (null? val)) (cdr val))
My song is over and I'm going home to bed
With this ineffable feeling that I've been misled
And just in case my point you have missed
Somehow I preferred (CDR (ASSQ KEY A-LIST))
(define (avalq key a-list)
(let ((val (assq key a-list)))
(if val (cdr val) #f)))
Then you can use the even simpler
(avalq k stuff)
throughout your code. "avalv" and "avalue" are left as an exercise for the reader.
Or, just (define (cdr* l) (if (pair? l) (cdr l) #f)) and you can be as CL:y as you like.
(cond ((assq key a-list) => cdr) (else #f))
will work. The second halve of this poem is a bit silly.
The `let' is completely unnecessary, and does not address the root cause
(which is that Scheme's cdr does not work on #f) in any way.
Of course, the kind Lispers will now volunteer to transliterate
(define (y f) (lambda () (f (y f))))
((y (lambda (f)
(if (= n 0) 1 (* n ((f) (- n 1)))))))))
into Lisp ;-)
Equal formatting nazi strikes again -- Scheme formatting altered to match the Lisp one below
(defun y (f) (lambda () (funcall f (y f))))
(setf (symbol-function 'fac)
(funcall (y (lambda (f)
(if (= n 0) 1 (* n (funcall (funcall f) (- n 1)))))))))
Why do you funcall f twice? Shouldn't the inner one be #'?
The Scheme expression ((f)) is in Common Lisp either (funcall (f)) - if f is a function - or (funcall (funcall f)) - if f is a variable with a function as a value. In above example f is a variable.
Scheme took all defun out of Lisp! — Faré
Here's my take on this whole Scheme-vs-Common-Lisp issue. Common Lisp's sole purpose is providing a practical environment in which to program real-world applications. In this regard, though, it doesn't offer anything
that younger systems like Python or Ruby don't. Therefore, there's just no reason to learn Common Lisp nowadays. Scheme, on the other hand, has a completely different purpose, for which it is well suited: teaching. There's no serious alternative to Scheme in teaching basic principles of computer science. Scheme thus still has a reason to exist, while Common Lisp does not.
Now I know that I will be jumped on by lots of SmugLispWeenie
s claiming that Lisp's macro support and CLOS' multimethods are so
cool and kick the pants off Python, but I have still not seen a single real-world problem that Common Lisp makes significantly more readable or maintainable (which is what counts in a programming language). Apart from pattern-matching, maybe (which, I'm sure, could be done elegantly in Python and especially Ruby, too, but not a lot of people seem to care much about).
I'd be glad to be proven wrong, though. So please show me some real-world problems that Common Lisp solves in a significantly better, more maintainable way than Python and Ruby do. Until then, I'll stick to Scheme and Smalltalk for studying and Python for working.
No one has ever been "proven wrong" (according to them) in any LanguagePissingMatch; stick to whatever languages you like, who cares? Do see BlubParadox, though. Also I regularly discover new depths to Lisp that I didn't previously grok. The same is true for C++, but in a bad way. The same is not true of C. Is it true for you for your favored languages? Just something for you to think about.
Ha! Well said!
I think I know what you mean regarding C++... :)
Seriously, though, Ruby is quite fascinating in this regard, but I think that's exactly the kind of thing that makes me like Python. Everything is just so obvious, whether you are a beginning programmer or a wizard. Of course, there are some dark corners, but only very few. -- MatthiasBenkard?
You were wrong about not being proven wrong, Doug, for I have
been proven wrong -- by Common Lisp itself. I've been playing around with it for a while now, and I absolutely love it. In fact, Common Lisp seems to be more of a drug than a programming language, and a highly addictive one, too. Whenever I try to get away from it, even just a little (in order to write a shell script, say), it pulls me right back! I can't stand using or even reading anything else anymore! HELP!
Man... Had I known this in advance, I would've never tried it. Now I have to live with my addiction. IT'S ALL YOUR FAULT! ;)
You mean, "few dark corners" on Ruby and Python? Lots of dark corners. Check up the Procs vs Lambdas, or the Eigenclasses (a.k.a. Singleton Classes) on Ruby, e.g. That
is confusing. And, yeah, Common Lisp, Scheme, and all Lisps are drugs, not programming languages. We have to ban Allegro and LispWorks
, for selling highly addictive drugs. The only thing I can stand now are Haskell and Perl, which, IMHO, are the only languges which can survive amidst all the junk. -- Daniel Valio
See also http://dept-info.labri.u-bordeaux.fr/~strandh/Teaching/Langages-Enchasses/Common/Strandh-Tutorial/diff-scheme.html