Don't Panic!

aurellem

Written by Robert McIntyre

1 Welcome

Welcome to 6.945/6.S081, Adventures in Advanced Symbolic Programming!

This is a basic guide to getting started with the programming tools we will be using in the class, which are mit-scheme and either edwin or emacs, two very similar editors.

2 Install mit-scheme

First off, get access to GNU/linux system. You can either use the Athena machines, or your own system. While it is certainly possible to install mit-scheme and edwin/emacs on windows and macs, we don't offer support for those systems.

You have two options when it comes to getting access to the implementation of scheme (mit-scheme) that we need for the class.

2.1 Use Athena

  • Advantages:
    • easiest option
  • Disadvantages:
    • requires internet connection or physical presence at an Athena cluster.

Just log onto your MIT Athena account and execute:

   add 6.945

Now you have access to mit-scheme.

If you type

   which mit-scheme

You will see that mit-scheme is now provided by the 6.945 Athena course locker.

Remember that you can always access Athena by using ssh from any operating system, so you can have the convenience of Athena and the convenience of using your own machine. For Windows, use PuTTY to access Athena. For mac users, you can just use ssh.

2.2 Install mit-scheme binaries on your own system

  • Advantages:
    • Use your own computer
  • Disadvantages:
    • Slightly more complicated than Athena

Go to the mit-scheme project website here: http://www.gnu.org/software/mit-scheme/, and download the appropriate binary package for your system. If you don't know whether you to pick the "i386" or "x86-64" option, run

   uname -m 

To determine what type of processor you are using.

In order to install the software, you should choose a directory on your system where you would like to put the files you download, and another directory where you will place the final product after you have compiled everything. One common place to put these files is /usr/local/. Here is a transcript of when I installed mit-scheme on my 64 bit GNU/Linux system for reference.

# I like to put the compiled scheme files inside the directory I use
# for the class. Another reasonable option would be to use some
# temporary directory for SCHEME_DOWNLOAD and /usr/local for
# SCHEME_INSTALL
SCHEME_DOWNLOAD=~/6.945 
SCHEME_INSTALL=~/6.945/artifacts

mkdir -p $SCHEME_DOWNLOAD
cd $SCHEME_DOWNLOAD

# for 32 bit GNU/Linux system, use mit-scheme-9.1.1-i386.tar.gz
# instead of mit-scheme-9.1.1-x86-64.tar.gz here.
wget -c http://ftp.gnu.org/gnu/mit-scheme/\
stable.pkg/9.1.1/mit-scheme-9.1.1-x86-64.tar.gz

tar xf ./mit-scheme-9.1.1-x86-64.tar.gz

cd ./mit-scheme-9.1.1/src
# This prepares the build system for scheme and tells it to install
# the binaries that will be created to SCHEME_INSTALL
./configure --prefix=$SCHEME_INSTALL

# This does the actual building of mit-scheme
make -j9 compile-microcode

# And this copies the installed files to SCHEME_INSTALL
make install

# try out your new mit-scheme system
cd $SCHEME_INSTALL/bin

./mit-scheme --version

You should see something like:

MIT/GNU Scheme running under GNU/Linux
Type `^C' (control-C) followed by `H' to obtain information about interrupts.

Copyright (C) 2011 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Image saved on Monday January 20, 2014 at 3:00:50 AM
  Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/C 4.118
  Edwin 3.116

3 Get an Editor

There are two editors we support in the class: edwin and emacs. In contrast to other editors, both edwin and emacs are highly programmable – they empower you to change the editor to suit your particular needs. Each editor is almost entirely programmed in its own extension language: mit-scheme for edwin, and a dialect of LISP called elisp for emacs. What you make of these editors is limited only by the bounds of your creativity.

3.1 Which editor should you use?

  • edwin
    • entirely written in mit-scheme (you can extend it using stuff you learn in 6.945)
    • offers a better integrated scheme debugger than emacs
    • based on an older version of emacs (version 19) and has not been developed much since.
    • fairly anemic library – edwin is probably not that good a choice for editing python code, for example.
    • no online presence or community
    • Prof. Sussman uses edwin and he can help you with your edwin related problems
  • emacs
    • MUCH larger online community than edwin. If you get stuck on something there is likely someone on the internet who has already developed a solution.
    • Vast library of already-written code to customize emacs for almost any usage. org-mode alone is one of the many additional tools that comes with emacs that might make you want to consider it over edwin.
    • Still in active development, so is more "modern" than edwin, including things like Unicode support and integration with almost every language and version control system.
    • uses elisp, a fairly kludgy dialect of lisp, as an extension language
    • not as much integration with mit-scheme than edwin
    • slightly more difficult to set up for 6.945 than edwin
    • I use emacs and can help you with your problems

Edwin is well suited for learning scheme and has been a traditional part of 6.001 and 6.945 at MIT for decades. If you choose it you'll be using a system that was specifically created to empower you to hack mit-scheme, whether you're a novice or an expert.

If you choose emacs, then you'll be putting in time learning an editor that many expert programmers consider to be the best programming tool in the world. It is likely that you will be able to use emacs for programming projects outside of 6.945, and for many more use cases than writing code in mit-scheme.

We support both editors in 6.945.

3.2 Installing Edwin

If you chose edwin, then you don't really have to do anything – it comes with mit-scheme. If you're on Athena, and have added the 6.945 course locker, you can start edwin by executing

edwin

If you're on your own system, you can start edwin by executing

mit-scheme --edit

If the mit-scheme binary is not on your PATH, you'll have to type in the full path to the mit-scheme binary on your system. On my system, I installed mit-scheme to /home/r/proj/6.945/scheme, so I use

/home/r/proj/6.945/scheme/bin/mit-scheme --edit

to start edwin.

You can easily make an "edwin" command on your own system by adding an alias to your ~/.bashrc file. Add something like the following line to your system:

alias edwin="mit-scheme --edit"

You may also want to increase the heap size to get better performance. For 32 bit systems, use:

mit-scheme --edit --heap 10000

For 64 bit systems, you can use:

mit-scheme --edit --heap 100000

3.3 Installing Emacs

If you are on Athena, then emacs is already installed and ready to use. If you are running Ubuntu, execute:

sudo apt-get install emacs

If you are running arch linux, execute:

sudo pacman -S emacs

Otherwise, check your distribution's package repository and use the recommended emacs package. If you're using windows, the following might be helpful http://ftp.gnu.org/gnu/emacs/windows/.

3.4 Customize your Editor

Neither emacs nor edwin are that fun to use without customization. Each editor reads a config file when it starts up, and executes the code in that config file. For emacs, this is a file in your home directory called .emacs, written in elisp. For edwin, this is a file in your home directory called, you guessed it, .edwin, written in scheme.

It can be very daunting to develop your own custom "dot-file" for these editors, so here are some settings to get your started.

3.4.1 Emacs dot-file

In addition to a file called .emacs in your home directory, emacs also uses a directory in your home directory called .emacs.d to store related files. Our default settings for 6.945 provide layouts for both .emacs and .emacs.d.

6.945 provides you two options for configuring emacs : a "basic" setup and an "extra" setup.

The "basic" setup contains just those things that you need to use scheme, along with a few other functions for manipulating fonts and printing your buffers.

The "extra" setup contains everything in the "basic" setup, along with several color modes, a terminal emulator, and a few other things.

To get started with emacs, first download our emacs setup file:

basic OR extra.

Here is a transcript for installing the "extra" emacs config.

wget http://web.mit.edu/6.945/dont-panic/emacs-extra-config.tar.bz2
tar xvf emacs-extra-config.tar.bz2
cd emacs-extra-config
make install

If when you execute

make install

make tells you that ~/.emacs.d or ~/.emacs already exist, then you should check to see if they have anything important that you want to keep.

If you don't care about your previous emacs settings, you can run

make remove-emacs-config

to delete whatever default settings you may have. You can also use this to start over if you ever mess up your emacs config and want to reset everything.

Be sure not to do this if you want to keep your current emacs settings! If you already have settings you like, feel free to pick and choose from the files and configurations available in the archive file.

Finally, you should edit ~/.emacs and replace the line:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;         MIT-scheme config                        ;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; This is the place where you have installed scheme. Be sure to set
;; this to an appropriate value!!!
(setq scheme-root "/mit/6.945")

to refer to the proper path to your mit-scheme install. For Athena, this is /mit/6.945 (and is already configured for you). If you installed scheme on your own system, it is the directory you used for $SCHEME_INSTALL.

3.4.2 Edwin dot-file

Edwin has a lot less configuration options available than emacs, because there are less library files available. Here the settings Sussman and myself use:

http://web.mit.edu/6.945/dont-panic/.edwin

They provide firefox-like font resizing and some good default colors.

To install these settings for yourself, simply place the .edwin file in your home directory.

cd ~
rm -f .edwin
wget http://web.mit.edu/6.945/dont-panic/.edwin

3.5 Exploring your Editor

Both edwin and emacs provide excellent, self-contained tutorials that will walk you through all the basic commands you need to know to use the editor.

To view the tutorial, execute:

C-h t

That means to hold down the CTRL key press the "h" key, release the CTRL key, then press the "t" key.

You can also always see the available key commands by executing:

C-h m

This will tell you all the commands available in your current mode.

Now go do that tutorial!

3.6 Discovery

How do you know what sort of things you can do in your editor? For example, how do you figure out that C-M-x will evaluate the scheme form at your cursor if you don't already know that? The answer is to use the following invaluable discovery commands:

C-h m
describes all the key bindings of the current mode you are using. You should read all the key bindings of both the scheme source code mode and the scheme REPL mode so you know what you can do.
C-h k
Each keyboard shortcut in emacs/edwin is bound to a longer, named function. If you know the keyboard-shortcut but don't know the name of the function the shortcut uses, this will tell you the long version if you enter the keyboard shortcut. (Question: what function does C-h k itself call?)
C-h v
This shows you the documentation of any variable and provides a link to the source.
C-h f
This shows you the documentation of any function and provides a link to the source.
C-h t
If you don't know how to use the basic navigation functions, use this to enter an interactive tutorial that will show you the ropes.
C-h l
This displays the last 200 keystrokes you have typed. If you just accidentally did something cool and want to repeat it again, see what you typed with this.

Now seriously, use C-h m and take a look at all the different things you can do in your scheme mode and at the repl.

4 Workflow in 6.945

mit-scheme is part of a long tradition of computer languages in the LISP family of languages, which includes common lisp, clojure, elisp, maclisp, zetalisp, etc. LISP is almost as old as programming itself, having been created just a year after Fortran, the first "high-level" computer language.

The most important thing about programming using scheme, and any LISP for that matter, is to use the REPL.

REPL stands for Read Eval Print Loop, and it is similar to working at an interactive terminal where you enter commands, change your commands based on the results of previous commands, and save things for later use. REPL oriented programming stands in contrast to batch-based programming: instead of writing a program and then running/debugging it, you build your program piece by piece, playing with and changing each little piece as you construct them.

Generally, as you are programming in scheme, you will have one window which contains the code you are writing, and one window which serves as your REPL. You write some code (perhaps a single function), evaluate that code, then move over to the repl and experiment with the code you just wrote. Based on your repl interaction, you go back to your code and make changes, and then the cycle repeats. You can also run some tests in the REPL and then copy the results of those tests into your main source file, to use as documentation of what the function is supposed to do for certain inputs. This will be an effective way to prepare psets – you write code, then copy the answers to the problem from the REPL back to your source file.

To start a REPL in emacs, execute:

  M-x run-scheme

In edwin, you already have a REPL running in the scheme buffer.

4.1 REPL tutorial

You can try using the REPL right now! First, create two buffers: one with a mit-scheme REPL and one displaying an empty scheme file. The file should end in ".scm" so that emacs=/=edwin can recognize that it is a scheme file and provide syntax highlighting and REPL integration.

Go to the REPL, type:

(fib 5)

And press <enter>.

You will see that you get an error, because the variable fib is not yet defined.

Now go to your scheme file and define fib with

;;;; Fibonacci Numbers

(define (fib n)
  ;; Calculate the nth Fibonacci number recursively
  (if (< n 2)
      1                                 ; base case
      (+ (fib (- n 1)) (fib (- n 2)))))

While the cursor is inside this form, press C-M-x (in emacs) or M-z (edwin) to evaluate the form and send it to the REPL. Now go back to the REPL and enter (fib 5) again and you will see the function you defined in your scheme file evaluated and printed to the screen. This is really cool! If this were a C or Java program you would have to write a small test-harness, re-compile and then run the program again to do what you have just done. As you work on building more complicated programs, you will begin to see the power of this method.

4.1.1 Note on comments

In scheme, the ; character is the comment character. But historically, the number of ; characters used has meaning. Four ;'s means that this comment is the title or header of the file. Three ;'s means the comment should be left justified. Two ;'s means that the comment should be indented as if it was code, and a single ; means that the comment should be right justified.

There is also the #| ... |# multi line comment, similar to the /** ... **/ comment in C and C++. This comment is useful for including test cases. If you were completing the definition of fib for a pset, you might use a multi-line comment to include test cases like so:

;;;; Fibonacci Numbers

(define (fib n)
  ;; Calculate the nth Fibonacci number recursively
  (if (< n 2)
      1                                 ; base case
      (+ (fib (- n 1)) (fib (- n 2)))))

#|
 (fib 5)
;Value: 8

 (fib 20)
;Value: 10946
|#

Note that use can evaluate the (fib 5) and (fib 20) scheme forms using M-z or C-M-x even though they are in comments.

5 Debugging scheme code

Many problems are transparent if you have an interactive debugger. Instead of littering your code with display statements, you can examine the values of local variables while your function is running.

5.1 Start the debugger

You can always start the debugger by evaluating

   (debug)

at a scheme REPL. When you do, you will see something like this:

   There are 4 subproblems on the stack.

   <stuff...>

   You are now in the debugger.  Type q to quit, ? for commands.

   2 debug> 

Try typing ? and familiarize yourself with the different options.

5.2 Simple debugging walkthrough

Let's debug the following scheme function:

(define (factorial n)
  (if (< n 2) 
      1 
      (* n (factorial (dec n)))))

At first glance this seems to be a reasonable definition – we return 1 if we are given 1 as input, otherwise we return n times the factorial of n decremented by 1.

Evaluate this definition and then attempt to evaluate

(factorial 3)

at the REPL.

You will see:

1 ]=> (factorial 3)

;Unbound variable: dec
;To continue, call RESTART with an option number:
; (RESTART 3) => Specify a value to use instead of dec.
; (RESTART 2) => Define dec to a given value.
; (RESTART 1) => Return to read-eval-print level 1.

2 error> 

Whenever an error is encountered during the course of evaluating an expression, mit-scheme puts you into this mode. These options give some limited access to the debugger. You can either choose one of these options or type (debug) to enter the debugger proper.

Here's an example transcript where I fix the problem (of dec not actually being defined) and repair the original factorial call while it is still being executed.

1 ]=> (factorial 3)

;Unbound variable: dec
;To continue, call RESTART with an option number:
; (RESTART 3) => Specify a value to use instead of dec.
; (RESTART 2) => Define dec to a given value.
; (RESTART 1) => Return to read-eval-print level 1.

2 error> (debug)

There are 8 subproblems on the stack.

Subproblem level: 0 (this is the lowest subproblem level)
Expression (from stack):
    dec
Environment created by the procedure: FACTORIAL

 applied to: (3)
The execution history for this subproblem contains 1 reduction.
You are now in the debugger.  Type q to quit, ? for commands.

Now that we're in the debugger, we can view the chain of procedure calls which led us to this situation.

3 debug> H
H
SL#  Procedure-name          Expression

0    factorial               dec
1                            ;undefined expression
2    factorial               (factorial (dec n))
3    factorial               (* n (factorial (dec n)))
4    %repl-eval              (let ((value (hook/repl-eval s-expression envi ...
5    %repl-eval/write        (hook/repl-write (%repl-eval s-expression envi ...
6    do-loop                 (begin (if (queue-empty? queue) (let ((environ ...
7    loop                    (loop (bind-abort-restart cmdl (lambda () (der ...

This is a stack trace like you might know from java or C. Each line in this list is called a subproblem, because scheme works expanding and evaluating forms until it determines a value. Lines 4-7 are procedures involving the REPL itself. Line 3, (* n (factorial (dec n))), leads to the subproblem of figuring out what (factorial (dec n) is, which leads to trying to evaluate (dec n) which is where our trouble starts.

We can view all the current bindings in the little environment created by the call to factorial this is like exploring the values of local variables in any other debugger.

3 debug> A
A
----------------------------------------
Environment created by the procedure: FACTORIAL
Depth (relative to initial environment): 0
 has bindings:

n = 3


----------------------------------------
Environment named: (user)
Depth (relative to initial environment): 1


----------------------------------------
Environment named: ()
Depth (relative to initial environment): 2

This is a very simple environment, with only n, which is set to the value we entered into factorial, 3.

Let's fix the problem – dec isn't defined, but we want it to be equal to the function (lambda (x) (- x 1)). Using P in the debugger we can move out of the environment of factorial and back to the user environment, where we can define dec.

3 debug> P
P
Environment named: (user)
Depth (relative to initial environment): 1

3 debug> V
V

Evaluate expression: (define (dec x) (- x 1))

Value: dec

Now, we re-evaluate the original problematic subproblem and continue the original call to factorial.

3 debug> Z
Z

Expression to EVALUATE and CONTINUE with ($ to retry): $

;Value: 6

1 ]=> 

Note that if you are using edwin, you will be given an option to "start the debugger" in addition to the other options. If you start the debugger in this way, then you will get a very nice looking window that constantly displays many of the things you could otherwise access through the commands you have just been shown. Try it out; it's neat!

Date: 2014-02-05 13:36:14 UTC

Author: Robert McIntyre

Org version 7.7 with Emacs version 23

Validate XHTML 1.0