I've been getting emails asking me questions about how I am developing my Scheme projects on the iPhone. These questions tend to poke at general issues with development: how do you make changes appear quickly? How do you debug errors?
There have been several interesting discussions which I would like to start sharing here on my blog in a series of articles. I hope to integrate comments here sometime soon, but for now you can see what I've been doing and email me an questions or comments about it.
These discussions will usually be centered around one thing: incremental development.
First, I'll show you the power of "growing your development environment," and explain why you should be using an IDE or text editor that lets you extend it easily.
Emacs will be the tool of choice in these discussions because I believe it is the best out there for development. Sure, you've heard that before, but you wave your hand at those old fogies and turn towards "fancier" editors that were built in this decade. Well, it may not be the right thing for everybody, but hopefully these articles will shine some light on why many live by Emacs.
The reason Emacs is great is because it is built off of a dynamic programming language, Emacs Lisp (elisp), which you have complete access to. You can write code and evaluate it instantly to change the behaviour of Emacs. This makes it incredibly fast to write Emacs libraries and is the reason why there are so many rich and powerful Emacs libraries out there.
I always run my programs as a REPL within Emacs (basically a subprocess with a prompt for receiving code to evaluate). Doing so is the cornerstone for incremental development because Emacs provides several functions for sending code to the program to be evaluated. I even make my games connect to Emacs and provide a REPL. See "Remote REPL in Emacs" in this post for more details.
Since I have the ability to interactively send code to my running program, something that I have found very useful is to wrap up common tasks into elisp functions and bind those functions to keys.
For example, I commonly want to "restart" my game, or set it back to a certain state so that I can test something many times quickly. With the following elisp code, all I have to do is press `C-x C-r` and my game is set back to normal.
(defun project-send-string (str) (comint-send-string (scheme-proc) str)) (defun project-restart () (interactive) (project-send-string "(set! LIFE MAX-LIFE)") (project-send-string "(set! EXISTING-CRACKS '())") (project-send-string "(set! FAILED #f)") (project-send-string "(set! SCORE 0)") (project-send-string "(set! overlay-list '())") (project-send-string "(load-randomized-cracks)") (project-send-string "\n")) (global-set-key "\C-x\C-r" 'project-restart)
What's happening is that Emacs is connected to my running program using this remote debugger which uses Emacs' Scheme functionality, and it tells the Emacs `comint` library to send several expressions to the connected program, which it evaluates.
It's very useful, and you could build up a collection of useful commands and tests all invoked by simple keystrokes. This is why it's important to be able to extend your environment and tailor it to your very specific needs.