Running Allegro Common Lisp From Emacs |
The advantages of running ACL from within Emacs are many. While the interface between ACL and Emacs is quite sophisticated and complicated, most of the complexity is hidden, and the sophistication will help you with many common operations. For instance, you gain the ability to type Lisp expressions into an editor buffer, using the full power of the editor to modify and change them, and with a single keystroke, have Emacs evaluate these expressions. In addition, documentation on functions, arguments to functions, and source files containing function definitions can all be called up with a single keystroke.
To run ACL from within Emacs requires that you `tell' Emacs how to connect to ACL. The means you will need to add some lines to your .emacs file for initializing Emacs. The complete listing of these commands follows. However, you need not retype all these commands. They can be found in the file allegro-dot-emacs-additions, but look exactly like:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; The Hooks for using Allegro Common Lisp from within Emacs (setq load-path (cons "/usr/local/allegro/home/emacs/fi" load-path)) (load "fi-site-init") ; It appears loading fi leaves emacs default directory hosed. Thus, ; let's set it back to the current directory ;;; Customize the common ; lisp invocation command for emacs. (setq default-directory (expand-file-name ".")) ; The default buffer name is "*common-lisp*" but this can be changed (setq fi:common-lisp-buffer-name "*common-lisp*") ; The directory should be where emacs was started (setq fi:common-lisp-directory (expand-file-name "./")) ; The default buffer image name is "cl" but we use pb_clim2xm_composer (setq fi:common-lisp-image-name "class-lisp") ; The image arguments can be modified, new arguments can be added (setq fi:common-lisp-image-arguments nil) ; The host can also be specified ;(setq fi:common-lisp-host "faure") (defun acl () "This function starts up Allegro Common Lisp with your defaults" (interactive) (fi:common-lisp fi:common-lisp-buffer-name fi:common-lisp-directory fi:common-lisp-image-name fi:common-lisp-image-arguments) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;After modifying your .emacs file, you can start up Emacs and then type ESC-x acl which will open a window and start up ACL in that window. In case you cannot think of something to say, take lisp for a spin by typing the following:
(sqrt 12321)Lisp will come back telling you that the square root of 12,321 is 111. The tutorial below has more things to try.
USER(1):
USER(22): (+ 1 2) 3The ( opens the expression, the symbol + indicates you wish to evaluate the following arguments with the function that performs addition, the arguments follow, and finally the expression is closed off with a right parenthesis ). The response, 3, is printed on the following line. So far pretty elementary... You can nest expressions in the following fashion.
USER(23): (+ (+ 1 2) (+ 3 4)) 10Many Lisp functions also allow variable numbers of arguments. Thus, you could accomplish the same addition with:
USER(24): (+ 1 2 3 4) 10You can record values for later use by binding them to variables. Thus, you can introduce the symbol foo and bind it to the value returned from an expression.
USER(25): (setf foo (+ 1 2 3 4)) 10 USER(26): foo 10The first expression has bound the value 10 to the variable foo. The second expression, consisting only of the symbol name, when evaluated, returns the value of the symbol.
defun
. For the moment, do not worry about what
'special form' means, we'll get there in lecture.
Thus, to create a function to increment a value by 1, you type in
the following:
USER(27): (defun add-one (x) "Adds one to its argument" (+ x 1) ) ADD-ONEYou can now use this function just like any other function in the language.
USER(29): (add-one 12) 13No introduction is complete without the "Hello World" program. So here it is:
USER(30): (defun hello-world () "Repeat after me, hello world" (format t "Hello World") ) HELLO-WORLD USER(31): (hello-world) Hello World NILWith this example, we touch on a subtle point. A function can be instructed to print text using the
format
function. In this case, the text appears in the obvious place, the
interaction window. What the function prints and what it returns
as its value when evaluated should not be confused. The Hello
World appearing when you evaluate the function is the
consequence of executing the format
statement. The
NIL
on the following line is the actual value returned
by the function. NIL is a particularly important value. It
has several interpretations which will only really make sense once
you are more familiar with the basics of lisp. Think of it now as
simply a null value.
Let's close out this section with a variant upon hello-world.
USER(32): (defun hello-my-name-is (name) "Program to greet newcomers other than Bob" (if (string-equal name "Bob") (format t "Go Away Bob") (format t "Nice to meet you ~A" name)) ) HELLO-MY-NAME-IS USER(33): (hello-my-name-is "Ross") Nice to meet you Ross NIL USER(34): (hello-my-name-is "Bob") Go Away Bob NIL
USER(53): (ehllo-world) Error: attempt to call `EHLLO-WORLD' which is an undefined function. [condition type: UNDEFINED-FUNCTION] Restart actions (select using :continue): 0: Try calling EHLLO-WORLD again. 1: Return a value instead of calling EHLLO-WORLD. 2: Try calling a function other than EHLLO-WORLD. 3: Setf the symbol-function of EHLLO-WORLD and call it again. [1] USER(54):The ACL debugger is a tremendously useful tool. However, our goal for the moment is simply to let you get back to `top-level' and forget about your typo. What you notice is that a [1] has appeared to the left of the usual prompt. Simplifying dreadfully, this means Lisp has caught your mistake, left a place holder as to what you were attempting to do, and is now again letting you evaluate expressions. The expressions can include directives to the debugger. The most basic directive means essentially 'get me out of here' and can be given by typing :pop. For example:
[1] USER(54): :pop USER(55):You could alternatively type :help and Lisp would print out a complete listing of commands you can enter.
hello-my-name-is
, but you are not quite sure what it
does. You can call up its documentation string by simply starting
to type the function, i.e.
USER(35): (hello-my-name-isNow, with the cursor placed to the right of the function name, type the following keystrokes:
Esc-Sh-FTo clarify our conventions for identifying keystrokes, this means you should depress the escape key, followed by the shift and F keys together. (Optionally, on some Sparc keyboards there is a key next to the space bar with a diamond on it. Anything that can be accomplished by typing escape followed by other keys can be done with the diamond depressing the diamond key while depressing the other keys.)
Emacs will now ask you in the small one line window at the bottom to confirm your request; it will say:
Function documentation for symbol: (default hello-my-name-is)Typically you want the default, and so by simply entering Ret, Emacs will print the documentation string to either this same display line, if it is small, or to a help window if it is larger. So, in this case, you will see displayed:
Program to greet newcomers other than BobThis is your first way of finding descriptions of what functions in Lisp do.
One minor digression on the point of documentation strings, in a major step backwards, Allegro Common Lisp has adopted the convention of other Unix Common Lisp systems and saved disk and memory space by removing documentation strings from the common functions, which is too bad since systems 15 years ago running on Lisp Machines with 8MB of memory routinely kept complete documentation available with only a keystroke. When writing your own Lisp code, it is very good practice to include documentation strings.
The function expt
is used to raise a number to a
power. This is a classic example of a function where one might
forget the order of the arguments. Hence, you can type the
following (leaving the cursor to the right of the last character)
USER(51): (exptand now type
Esc-Sh-aEmacs will ask you in the bottom window to confirm your request. Simply hit Ret and it will display the following:
EXPT's arglist: (BASE POWER)This tells you the function takes two arguments. The first is the base and the second is the power to which you want it raised. Thus, to raise 8 to the 3rd power, you would type:
USER(51): (expt 8 3) 512These are the two most basic and I find commonly used control keys for gaining information. There is one more mechanism which is independent of the Emacs to Lisp interface but still incredibly useful, and that is the
apropos
function
USER(52): (apropos 'hello 'user) HELLO-MY-NAME-IS [function] (NAME) HELLO HELLO-WORLD [function] ()The function
apropos
looks for all things defined
which contain the indicated string in their names. The way you
restrict attention to those things in the user package is
with the second argument. I recommend doing this until you
understand more about packages: otherwise you'll see many things
which will make little sense to you.
Note that you are told what things it finds, along with whether they are functions, and if so what arguments they take.
Let's begin by creating a file. You can do this easily in Emacs using the keystrokes C-x C-f. Again, this is shorthand for typing control x followed by control f. Emacs will now ask you to enter the name of the file at the bottom of the screen. For this tutorial you should type:
my-name-is.lispBe aware that Emacs may already give you a path to which what you type is appended. If the path is to the directory where you want to put the file (which it should be by default), this is helpful. However, if you don't watch and it tries to create the file in some other directory, this can lead to problems.
If a file of this name already exists, you will now be in a new buffer looking at the contents. More likely, no such file existed beforehand, and you are now looking at a new buffer which is empty.
For this tutorial, your file my-name-is.lisp should contain the following:
;;; File containing a simple function example (in-package user) (defun my-name-is (name) "Program to greet any newcomers other than the Bob" (if (string-equal name "Bob") (format t "Go Away Bob") (format t "Nice to meet you ~A" name) ) )A copy of this file can be found at my-name-is.lisp.
Now you are ready to learn something about how to communicate between files containing your Lisp code and the Common Lisp buffer.
C-c C-bYou will see it display the message that it is compiling. If you have entered everything correctly, it will quickly follow the compiling message with the word done at the bottom of the screen.
Now you can go to the Common Lisp buffer and do the following:
USER(61): (my-name-is "Ross") Nice to meet you Ross NIL USER(62): (my-name-is "Bob") Go Away Bob NIL USER(63):Your function has become part of the Lisp environment and can be used like other functions.
defun
expression. This is after the final
) which closes off the function at the bottom of the
file. Now simply type:
C-c C-sTry this by changing Bob to your own name and running the function. In my case, I modify the function so it appears as follows:
(defun my-name-is (name) "Program to greet any newcomers other than the Ross" (if (string-equal name "Ross") (format t "Go Away Ross") (format t "Nice to meet you ~A" name) ) )Then I place the cursor at the end of the function and type C-c C-s. The compiling message followed by the done message appears at the bottom of the screen. Now if I call the function in the Common Lisp buffer I get the following response:
USER(64): (my-name-is "Ross") Go Away Ross NIL USER(65):
my-name-is
. A reminder about Emacs, to do
this, you can simply type:
C-x kIf you are already in the buffer containing your file, this will be the default and you need only hit return. Now, if you type:
C-x C-bEmacs will display a complete list of all the buffers as well as what files are associated with those buffers which represent files. Note some buffers, like the *common-lisp* buffer have no corresponding files.
A passing comment, one way to move between buffers is to move the cursor into this display, select a line naming a particular buffer and type f. This will bring up this buffer in the window.
Now, to see how Emacs can track down where you source code lives, go to the Common Lisp buffer and type out the name of the function
USER(66): (my-name-isand without completing it and leaving the cursor at the right most point on the line, type
C-c .Emacs will ask you the following question at the bottom of the screen:
Lisp Locate source: (default my-name-is)If you type return, then Emacs will find the source file in which this function is defined, load it, and open it up in a window. Initially, you may not find this capability important, but as you begin to manage larger programs, it can be very handy.
Comments:
howe@CS.ColoState.EDU
;
ross@CS.ColoState.EDU
Copyright © 1998: Colorado State University, CS Department.
All rights reserved.