Scheme

Scheme is one of the main dialects of LISP and is a dynamically typed impure functional programming language.

Scheme can be both compiled and interpreted.

Why would I learn this language?

Scheme is a syntactically simple language with many interesting features such as homoiconicity. It provides a powerful environment for learning about algorithms and functional programming, and computer science concepts in general.

Starting Points

Schemers.org: Education
A set of resources for people interested in Scheme as a tool in education.
Little Scheme
An online Scheme evaluator which can be used to run simple Scheme code.
How To Design Programs
A complete teaching guide and student resource for learning about computer programming and computer science.
PLT Scheme
PLT Scheme is an entire software stack including IDE for developing Scheme programs.
How to Design Programs
A complete beginners guide to programming with Scheme and designing programs.

Example Code

The following is an example of the Fizz Buzz problem. You can run and edit this program here.

(define (fizzify i)
    (cond
        ((and (= (mod i 3) 0) (= (mod i 5) 0)) "FizzBuzz")
        ((= (mod i 3) 0) "Fizz")
        ((= (mod i 5) 0) "Buzz")
        (#t i)
    )
)

(define (fizzbuzz i)
    (if (<= i 100)
        (begin
            (display (fizzify i)) (display "\n")
            (fizzbuzz (+ i 1))
        )
    )
)

(fizzbuzz 1)

Here is an example of the 100 doors problem implemented using functional concepts:

; door-open? : integer -> boolean
; Tells whether a given door is open at the end of the experiment.
; Since no pass larger than the door number can possibly affect it, we'll only run that many passes.
(define (door-open? door)
	(doh? door door))

; doh?, short for door-open-helper : integer integer -> boolean
; First parameter is the number of the door you're interested in.
; Second parameter is the number of the last pass you want to do.
(define (doh? door pass)
	(cond 
		[(= pass 0) true]                     ; on pass 0, make everything open
		[(= (remainder door (+ pass 1)) pass) ; if door number is 1 less than a multiple of (pass+1), ...
			(not (doh? door (- pass 1)))]     ; ... flip it
		[else (doh? door (- pass 1))]))       ; otherwise don't

; print-doors : list-of-boolean -> output, 1 line per list element
(define (print-doors doors)
	(for ((door-num (in-range (length doors))) (open? doors))
		(printf "Door #~a is ~a.~n" door-num (if open? "open" "closed"))))

; print-doors-up-to : integer -> output
(define (print-doors-up-to n)
	(print-doors (build-list n door-open?)))

; Run the program with n = 100
(print-doors-up-to 100)

Here is an example of the 100 doors problem implemented using imperative concepts:

(define (main)
	;; Initialize the array of doors to 0 (closed)
	(define doors (make-vector 100 #f))
	;; Process the doors
	(for* ([pass (in-range 100)]
		[door (in-range pass 100 (+ pass 1))])
	(vector-set! doors door (not (vector-ref doors door))))
	;; Return a list of open doors
	(for ([(door i) (in-indexed (in-vector doors))])
		(printf "Door #~a is ~a.\n" (+ i 1) (if door "open" "closed" )))

(main)

Further Reading

comments powered by Disqus