Lisp Scheme Differences

SchemeLanguage and CommonLisp (CL) are about as similar as Java and C++.

The following compares the standards for both languages. Many implementations offer extensions.

Common Lisp:

Scheme: Contributors: StephanHouben, NoelWelsh, 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:

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.


CommonLisp 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".

SiCp 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". http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1

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. -- AnonymousDonor

Of course, Lisp and Scheme are completely different worlds.


Scheme uses LexicalScoping throughout. CommonLisp uses LexicalScoping normally, and provides DynamicScoping for variables declared as special (see SpecialVariables).


There are several existing scheme and lisp implementations that are designed to be embedded into an application - Guile, Librep, DrScheme, MzScheme, 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
==================================================
by
  Ashwin Ram

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) (else nil))

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)) (else nil)))

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)) (else nil)))

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))

:-)

So write

(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.

Actually,

  (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))))

(define fac ((y (lambda (f) (lambda (n) (if (= n 0) 1 (* n ((f) (- n 1)))))))))

into Lisp ;-)

Equal formatting nazi strikes again -- Scheme formatting altered to match the Lisp one below


Sure:

  (defun y (f) (lambda () (funcall f (y f))))

(setf (symbol-function 'fac) (funcall (y (lambda (f) (lambda (n) (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 SmugLispWeenies 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. -- MatthiasBenkard?

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. -- DougMerritt

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?

Update: 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! ;) -- MatthiasBenkard?

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


CategoryScheme CategoryCommonLisp


EditText of this page (last edited January 4, 2011) or FindPage with title or text search