|
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)
3
The ( 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))
10
Many Lisp functions also allow variable numbers of arguments. Thus, you
could accomplish the same addition with:
USER(24): (+ 1 2 3 4)
10
You 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
10
The 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-ONE
You can now use this function just like any other function in the
language.
USER(29): (add-one 12)
13
No 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
NIL
With 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-is
Now, with the cursor placed to the right of the function name, type the
following keystrokes:
Esc-Sh-F
To 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 Bob
This 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): (expt
and now type
Esc-Sh-a
Emacs 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)
512
These 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.lisp
Be 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-b
You 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-s
Try 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 k
If 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-b
Emacs 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-is
and 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.