Scheme is probably the most useful little language I know. Having learned it in MIT’s intro Computer Science class 6.001: Structure and Interpretation of Computer Programs, I was surprised to discover that it made me significantly more productive than Java or C++, despite its simplicity. Not only was I able to quickly write symbolic software, which is where Lisps arguably excel, but I also found it easy to write more “odinary” programs, such as a web server.
The next few articles are going to cover some of the software I have written in Scheme, and assume basic familiarity with the language (if you have no experience with Scheme but have used other Lisps, you should be fine. Hakellers are also welcome.). If you have no experience with Scheme, however, fret not! There is a number of great (and free) learning resources on the Internet:
- Structure and Interpretation of Computer Programs (SICP)
- How to Design Programs
In order to run my code, you will need to install MIT Scheme – a cross-platform Scheme programming environment available at http://www.gnu.org/software/mit-scheme/. The website includes detailed installation instructions for Unix, Windows and MacOS. If you are running Ubuntu, you can simply use the package manager:
sudo apt-get install mit-scheme
That will take care of installing MIT Scheme and some additional tools, such as
scheme-mode for emacs.
In order to see if MIT Scheme has been successfully installed, type
mit-scheme in the terminal (or the command prompt in Windows). You should get an output similar to the following:
MIT/GNU Scheme running under GNU/Linux Type `^C' (control-C) followed by `H' to obtain information about interrupts. Copyright (C) 2010 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 Tuesday March 9, 2010 at 6:41:34 PM Release 9.0.1 || Microcode 15.1 || Runtime 15.7 || SF 4.41 || LIAR/i386 4.118 Edwin 3.116 1 ]=>
If that is what you see, great! You can now start editing and running Scheme code.
To edit Scheme code, you can use any of your favorite text editors, be it vim, Emacs or gedit. Personally, I do all of my Scheme development in Emacs, which is available in most Linux distributions, and can also be installed on MacOS and Windows.
If you are using Emacs and have installed MIT Scheme through the package manager, you should already have
scheme-mode available. Otherwise, you can get it from here. The following is a brief list of keyboard shortcuts I most commonly use:
||starts the Scheme interpreter in a new buffer,
||sends current buffer to the interpreter|
||sends the expression to the left of the cursor to the interpreter|
||(REPL) inserts previous expression at point|
||(REPL) inserts next expression at point|
When sending a buffer to the interpreter, make sure all your parentheses are matching, or you will get unexpected behavior when sending buffers or expressions later. If you do make this mistake, however, typing
C-c C-c at the prompt should fix it.
If you want to enable automatic paren matching (which you most likely will), append this snippet to your
(setq show-paren-delay 0 show-paren-style 'parenthesis) (show-paren-mode 1)
And if you ever create macros which you would like to be treated as keywords, you can use the following elisp function:
(defun register-scheme-keywords (keywords) (mapc #'(lambda (kword) (font-lock-add-keywords 'scheme-mode `((,(concat "\\(" kword "\\)") 1 font-lock-keyword-face)))) keywords)) ;; Example: (register-scheme-keywords '("defgen" "fluid-let"))
MIT Scheme comes with a great debugger. If you ever get an error, simply type
(debug) at the prompt. You will get an output similar to the following:
Subproblem level: 0 (this is the lowest subproblem level) Compiled code expression (from stack): (let ((value ###)) (repl-history/record! (%record-ref (cmdl/state repl) 5) value) value) subproblem being executed (marked by ###): (hook/repl-eval s-expression environment repl) Environment created by the procedure: %REPL-EVAL applied to: ((breakpoint) #[environment 11] #[cmdl 12]) There is no execution history for this subproblem.
The expression marked by
### shows which code was being executed when the execution stopped. This is the code that caused the exception. To move up or down the call stack, press “u” or “d”, respectively.
If you would like to use breakpoints, use the
breakpoint procedure. For example:
(define (my-function) (do-stuff) (breakpoint) (do-other-stuff))
When the interpreter hits the breakpoint, you can type
(debug) to inspect the execution.
Hopefully, by now you have a functional Scheme development environment up and running. If anything went wrong, feel free to ask about it in the comments.
Now, without further ado, let’s start hacking!