2. What is Scheme?
• Scheme is a dialect of Lisp, around since the
70s
• Functional, although not “pure”
• Extremely minimal, concise, and expressive
• Fully defined in R5RS [1]
• Build bigger parts from smaller parts
λ
3. Implementations
• Scheme by itself is the language specification
• There are many implementations of
Scheme, each with different strengths:
• Gambit-C: speed, portability
• PLT: ease-of-use, libraries
• Scheme48: modules, formal semantics
• etc.
λ
6. Functions
• `define` declares functions
• (define (multiply x y)
(other-function x)
(* x y))
• The last value is returned, so unless
`other-function` has a side effect, that call
is essentially ignored
• `define` also create variables
• (define foo 5)
λ
7. Functions
• `lambda` creates an anonymous function
• (lambda () (+ 1 2))
• (lambda (x y) (* x y))
• lambdas are ubiquitous in Scheme, too
powerful to fully explain here, but it’s
another dimension of Scheme’s
expressiveness
• Our “multiply” function could be defined as:
• (define multiply (lambda (x y) (* x y))) λ
8. Functions
• Functions are full closures with tail-
recursion where possible
• (define (foo x y)
(define z (get-z-axis))
(lambda () (+ x y z)))
• (define (bar)
(read-network-blocking-and-act)
(bar))
λ
9. Identifiers
• The name of an identifier is very flexible; can
contain almost any character
• Very expressive
• (define the-number 5)
• (define !@#$%^&* 10)
• (define (is-alive?) ...)
λ
10. Lists
• The list is Scheme’s fundamental data
structure
• Special syntax for lists:
• ‘(1 2 3 “foo”)
• ‘(1 2 3 (4 5 6))
• `(1 2 3 ,data) (define data “foo”)
• `(1 2 3 ,@data) (define data ‘(4 5 6))
λ
11. Lists
• Lists are made up of “cons cells” or pairs
• Fundamental list functions:
• car
• (car ‘(1 2 3)) => 1
• cdr
• (cdr ‘(1 2 3)) => (2 3)
• cons
• (cons 1 ‘(2 3)) => (1 2 3) λ
12. Lists
• Question: is a function not simply a list of
elements?
• ‘(define (foo x y) (* x y))
• Yes, it is.
• In fact, any code in Scheme is data — simply
a list of elements.
λ
13. Macros
• Macros are Scheme functions that take
arguments and expand into different code
• Macros usually parse code, which is easy in
Scheme because code is data!
• (define-macro (my-define func . body)
(let ((name (car func))
(args (cdr func)))
`(define ,name (lambda ,args ,@body))))
• (my-define (foo x y) (* x y)) expands into
• (define foo (lambda (x y) (* x y))) λ
14. Macros
• Macros are lazy
• Macros allow an extremely powerful tool for
extending the language for your needs
• Any new construct can be integrated
• You could redefine `if`
• Other macro systems exist which integrate
pattern matching and other features
λ
15. Say again?
• Because of consistency and conciseness, it’s
easy to write reusable, small bits of code in
Scheme, which is good
• Other libraries implement tons of stuff, such
as object systems, vectors, etc.
• SRFI’s
• Not covered: continuations, eval, and more
• Questions or comments?
λ
16. Practical Examples
• It turns out that it’s easy to implement
functional programming in an imperative
language like C [3]
• Gambit-C is a Scheme system which takes
Scheme and compiles it to C [2]
• Extremely fast and portable
• Easy to interface to C/C++/Obj-C
libraries
λ
17. Taking Scheme to the iPhone
• Cross-compiled Gambit’s run-time library
for the ARM architecture (for the iPhone)
• Compiled my Scheme code to C
• Linked everything together, and it ran fine!
• Wasn’t that easy? [4]
λ
19. Benefits
• Write iPhone apps in Scheme, of course
• Garbage collector
• Faster, real-time development
• Load in Scheme files at run-time
• Much more sane debugging
λ
20. Loading in Scheme at run-time
• Scheme has a `load` procedure which takes
a filename, loads in the code and evaluates it
• In Gambit, this function loads code at run-
time (`include` does the same thing at
compile-time)
• Compile an app with a `load` statement,
install it once, and develop with interpreted
code forever.
λ
22. Sane Debugging
• What is a REPL?
• Read-Eval-Print-Loop
• A debugger is a REPL with special
commands
• Gambit comes with a nice command-line
debugger, so we want this to work for our
iPhone apps.
λ
23. Sane Debugging
• Since code is simply S-expressions, it’s really
easy to parse, pass around the network, etc.
• We’ve created a “remote debugger” which
implements the functionality of a networked
REPL
• Instead of reading from the console, the
REPL reads and writes from/to a network
port
• A “debugging server” gives you access to
REPLs running inside the application λ
25. Optimizing
• Compiling to C makes it easy to fine tune
hotspots in your application
• (define fast-sqrt
(c-lambda (float) float “fast_sqrt”))
• Once you’ve written and debugged your app
sanely, profile and optimize specific parts of
your app
• Re-write small pieces of code in C
• Use `declare` in Gambit λ
26. Paredit
• Another benefit of concise syntax is more
advanced text editing
• Instead of thinking in terms of lines, think in
terms of S-expressions
• Paredit implements key-bindings in Emacs to
manipulate S-expressions
• Really powerful way of writing code
λ