This is a guide that I'll use to do the quick side-by-side Python/Scheme tour. Note: this is REALLY a brief tour: some of the programs in both languages are intentionally stupider than then should really be: I'm using a minimal language core. ********************************************************************** Simple arithmetic expressions [Python] >>> 1 ==> 1 [PyScheme] >>> 1 ==> 1 [Python] >>> 41 + 1 ==> 42 [PyScheme] >>> (+ 41 1) ==> 42 [Python] (2 + 4 * 6) * (3 + 5 + 7) [PyScheme] (* (+ 2 (* 4 6)) (+ 3 5 7)) Note that, compared to Python, Scheme has no concept of operator precedence, since all expressions are fully parenthesized. ********************************************************************** Functions are values. In Scheme, even the arithmetic operations are functions. Python doesn't implement the arithemtic operators this way: ### [Python] >>> + File "", line 1 + ^ SyntaxError: invalid syntax ### but Python does expose them as functions, in the 'operator' module: ### [Python] >>> import operator >>> operator.add ==> >>> operator.add(7, 19) ==> 26 ### [PyScheme] >>> + ==> (primitive-procedure ) >>> (+ 7 19) So practially everything in Scheme has the form: (OPERATOR OPERAND1 OPERAND2 ...) ********************************************************************** Defining and rebinding variables [Python] >>> language = "Python" >>> language = "The " + language + " language" >>> language [PyScheme] >>> (define language "PyScheme") >>> (set! language (string-append "The " language " language")) >>> language ********************************************************************** Defining functions I'm not sure how intentional this was, but Python's keyword for function definition is almost exactly the same as Scheme's. ### [Python] def square(x): return x * x def sqrt(x): return x ** 0.5 def hypotenuse(a, b): return sqrt(square(a) + square(b)) ### ### [PyScheme] (define (square x) (* x x)) ;; sqrt is a builtin in PyScheme, no need to redefine it. (define (hypotenuse a b) (sqrt (+ (square a) (square b)))) ### All functions in Scheme have an implicit "return". In fact, everything that we've done so far in Scheme is an expression with a value. This contrasts with Python, which separates expressions from statements. ********************************************************************** Flow-control ### [Python] def myMax(x, y): if x > y: return x else: return y ### ### [PyScheme] (define (my-max x y) (if (> x y) x y)) ### In contrast to Python's 'if' statement, Scheme's IF expression is an expression, so it can be combined in larger expressions. ### [PyScheme] (define (add-or-subtract a b choice) ((if (equal? choice 0) + -) a b)) ### ********************************************************************** Quick backtrack back to primitive expressions: Lists [Python] >>> numbers = [3, 1, 4, 1, 5, 9, 2, 6] [PyScheme] >>> (define numbersToFive (list 3 1 4 1 5 9 2 6)) In Scheme, LIST is a function that takes any number of arguments, and makes a list. Another major difference: Python's lists support random access by indexing. PyScheme's lists are actually chains of linked list nodes, or "pairs", and support access through CAR and CDR: [Python] >>> numbers[0] ==> 3 >>> numbers[5] ==> 9 [PyScheme] >>> (car numbers) ==> 3 >>> (define (nth l n) (if (= n 0) (car l) (nth (cdr l) (- n 1)))) >>> (nth numbers 5) ===> 9 In Scheme, CAR grabs the first element of a list, and CDR follows the tail of the list. We can check to see if we're at the end of a list by checking for NULL? We can also join a new head onto a list by using CONS, which is like list.insert(0, x), but since it's linked lists, this is not expensive. ********************************************************************** Ok, back to flow-control. By the way, let's look at the definition of NTH again: ### [PyScheme] (define (nth l n) (if (= n 0) (car l) (nth (cdr l) (- n 1)))) ^^^ ### Note: there's a loop! Another example: ### [Python] def my_index(L, x): """Looks for element x in L and returns its position. Raises an error if we can't find it.""" i = 0 while i != len(L): if L[i] == x: return i i += 1 raise IndexError ### ### [PyScheme] (define (my-index L x) (if (null? L) (error "Can't find it!") (if (equal? x (car L)) 0 (+ 1 (my-index (cdr L) x))))) ### The above is a bit messy: there's a bit of syntactic sugar in PyScheme to simulate a case analysis like this called COND: it's basically equivalent to if/elif/elif/else: (define (my-index L x) (cond ((null? L) (error "Can't find it!")) ((equal? x (car L)) 0) (else (+ 1 (my-index (cdr L) x)))))