Home Search Download Documentation
Help News Community SIGs
Current docs
Beginners Guide
Non-English docs
Language comparisons
Guido's essays
Topic guides
Email Us

Python vs. Scheme

Moshe Zadka writes:

Scheme is a lisp derivative properly tail recursive language. A short summary of differences between them:

Scheme has the following advantages to Python:

  • Supports proper closures, with lexical scoping.
  • Any function can be defined anonymously, via the lambda keyword.
  • Is supported by a standard (R5RS, IEEE)
  • Makes it easy to program in a functional style, i.e., without side effects.
  • Supports macros.
  • Mathematically oriented, rather then processor oriented, numeric model.
  • Supports fairly optimized compilation to native code.

Python has the following advantages to Scheme:

  • Standard object system (OTOH, "Any scheme programmer has written an object system, sometimes two")
  • Many builtin or standard functions for easy programmings, such as regular expressions or Internet connectivity.
  • Many builtin data types.
  • Relatively main-stream syntax.
  • One standard implementation: easy to write extension modules in a systems programming language (C/Java).
  • Main-stream control structures (while, for).

Python and Scheme are very similar languages, that came for very different backgrounds. Scheme grew up in the academia, at first as a language meant primarily for teaching. However, since it was the first Lisp dialect to support lexical closures, and had one of the first coherent numeric models, it soon became a "real" language. For example, it was highly favoured in MIT for writing AI applications.

Because Scheme was envisioned as a language it would be easy to "reason about it", a highly rigid syntax was developed: strictly prefix notation. Thus, the equation a*b+c would be written in Scheme notation as (+ (* a b) c). In addition, Scheme has a powerful notation for "deep lexicals" similar to Pythonic

[ (1,2), "hello", ("where", "are", ("you,)), ["somewhere", ('else', 1)]]
In Scheme, it would look like:
'#( (1 . 2) "hello" ("where" "are" ("you")) #("somewhere" ("else" 1))
Though it would be harder if we would want to include things which are evaluated at run-time, such as variables.

Scheme was developed to allow a mostly-functional (i.e., assignment-less) style, through the use of the tail-call-optimization (XXX add some reference).

On the other hand, Python was designed ab-initio to have more main-stream paradigms, so assignment is a fact of life in Python, and so are loops (Python is non-tail-call-optimizing, and it appears it never will be.)

In Scheme, it was decided it is easier to simulate objects which do not die, so a garbage collection scheme was decided upon (which means, an implementation may reclaim memory if it can prove that the contents of that memory will not matter to any future calculation).

Python has a simple reference-counting scheme, which conforms to the above definition of garbage collection (no pointers to object means the object won't matter), but is weaker then most implementations: it does not deal with cycles.

Scheme also has the useful invariant that "any valid scheme program is a valid s-expression" (an s-expression is a Scheme literal). This makes it easy to write programs such as interpreters, which intermix code and data.

On the other hand, the Python AST module is very hard to deal with (IMHO).

Scheme has many implementation, so care must be given if one needs to write portably, to avoid any implementation dependant behaviour. Each implementation was written for a different purpose: some implementations' greates strength is the existence of Scheme to C translators, while others' are the availability of a library (Stk, Scheme with Tk linked in) or easy embeddability (guile).

Python has two standard implementations (CPython and JPython) which are explicitly synchronised. Hence, it is easy to write portable Python code, and quite easy to write C code (or Java) as extensions to work with any Python in the world (modulu inherent C portability issues).

With R5RS, the latest version of the Scheme standard, came a standard macro facility, which can be used (or abused) to great effect.

Python does not have any macro facility, and it would be a hard thing to add to a white-space-oriented syntax.

Scheme has no standard library, though many attempts are being done to remedy this problem.

Python comes "with batteries included": code that connects to sockets, parses HTML, finds regular expression and serializes is just a fraction of Python's enormous standard library, which is enhanced by SIGs for numeric processing, string processing and data-base interfacing.