Declarative Languages

Agony Corner

Dear Dr Levine,

I was working away at my lisp session and a console window popped up. None of my lisp windows respond any more. What should I do?

Yours, Erroneous

Dear Erroneous,

You have run into what we in the trade refer to as "deep trouble". Every time your lisp system reports an error to you, you are supposed to do something about it. If you don't, then the errors keep piling up. When they get to about 8 or 9 deep, you get the console window.

Dismiss the console by typing :top into it. Then minimize it (do not close it).

If you decide to deal with errors before you get to that stage, you have the following options:

If you just want to get rid of the error prompt

type :top



type :c , a space, and one of the numbered options offered to you, e.g. :c 5

, a space, and one of the numbered options offered to you, e.g.

the key combination Alt-Shift-A will take you up one level of errors

If you want to debug the error

see chapter 3 of the "LispWorks User Guide"



use the right-button menu / Debug... to get useful options



from this menu, "Start GUI debugger" to give you an interactive window in which you can click on frames to see their arguments, double click to see the source (if it's your code, i.e. not system code), double click on arguments to open an "inspector" in which you can explore their structure more thoroughly



stay in the listener if you like and



type :b for a backtrace showing all the function calls, or :b followed by a number (e.g. :b 10) to see that number of calls

for a backtrace showing all the function calls, or :b followed by a number (e.g. :b 10) to see that number of calls



use :p and :n to navigate up and down the stack

and to navigate up and down the stack



use :v to see arguments to the frame you're on now



Dear Dr Levine,

I called my function and I think there must be something wrong because it never returned and that was ten minutes ago. How do I interrupt it?

Yours, Forever.

Dear Forever,

To interrupt the lisp process, type Control-Break into the listener. This should give you a debugging prompt.

Sometimes, you might imagine your code went away and never returned, but in fact you hadn't typed in a complete lisp form yet and the listener is hung reading your form. Test for this by seeing if the listener responds at all to mouse clicks, etc. If it does then it's still waiting for input. Check you closed all your lists, strings, etc. As a last resort, Alt-K will give you a fresh prompt and you can repeat the damage.



Dear Dr Levine,

How do I find out what a function does? How do I find the function I need to do a job?

Yours, Lookitup.

Dear Lookitup,

To find out what a Common Lisp function does, look it up first in Graham. For further detail, try Cltl2 online and / or the HyperSpec (under Help / Manuals menu as "ANSI Common Lisp Standard" or go to LispWorks Browesable Documentation from your start menu). To get direct to the correct HyperSpec entry for a symbol, click on that symbol and use the key combination Control-Shift-D. This will prompt you (see thin window at bottom of listener / editor) to confirm the symbol you're interested in: type return and the html doc will be displayed for you.

To find related functions from a HyperSpec page, try the icon of an up-arrow - this will take you to a dictionary of related concepts.

To get rapidly to see the argument list for any function (yours or system), use the key combination Alt-=.

To get a list of functions with related names, try the lisp function apropos . Example:

CL-USER 14 > (apropos 'apropos 'CL) APROPOS -- #<function APROPOS 20200D02>

APROPOS-LIST -- #<function APROPOS-LIST 2020DE0A> CL-USER 15 >

(apropos 'a 'CL)

Dear Dr Levine,

I get muddled between the listener and the editor, and between files and buffers, and all that. Can you sort me out?

Yours, Troubled.

Dear Troubled,

Think of the listener as a scratch-pad, and the editor as where you generate your code. Points to watch out for:

the editor window may have several files on the go at once. To switch between them, either use the "buffers" tab (double click on the buffer you want to edit), or use the key combination Control-X B.

when you save a source file from the editor, make sure it really has a .lisp extension. You have to type this in explicitly - the dialog box claims to be showing you files of type .lisp (and indeed it is doing that) but this does not mean that it will supply that for you as a default file type. If you mess up, rename the file (the lisp function rename-file , or "Alt-X Rename File", or the desktop).

- the dialog box claims to be showing you files of type .lisp (and indeed it is doing that) but this does not mean that it will supply that for you as a default file type. If you mess up, rename the file (the lisp function , or "Alt-X Rename File", or the desktop). to open a file, use the File / Open menu from the podium, or the "open file" icon on the podium, or the key combination Control-X Control-F, or the right-button File menu.

to save a file, you have the obvious counterparts of all the above ways to do it. The key combination for "save" is Control-X Control-S and for "save as" it's Control-X Control-W. Otoh, Control-X S will save all your files, which is handy if the pub beckons.

your files, which is handy if the pub beckons. while I think of it, be aware that Control-X Control-C is "save files and exit".

don't forget Control-H B to see the full unexpurgated list of all these key bindings.

to get the contents of a buffer loaded into the lisp, use the right button Buffer menu. Compiling takes a little longer that evaluating but is more likely to find syntax errors up front. On the other hand, interpreted code is often more debuggable, as the debugger has access to all your local variables. Pay heed to all compilation warnings. Type a space bar when it asks you. Use the "Output" tab to see it again if you need this.

loaded into the lisp, use the right button Buffer menu. Compiling takes a little longer that evaluating but is more likely to find syntax errors up front. On the other hand, interpreted code is often more debuggable, as the debugger has access to all your local variables. Pay heed to all compilation warnings. Type a space bar when it asks you. Use the "Output" tab to see it again if you need this. to get the contents of a file loaded into lisp, use the right button File menu, or the podium's file menu. Note that in this case, compiling a file does not imply loading its code too. So you need to compile and load it. Compiled files are of type .fsl.

loaded into lisp, use the right button File menu, or the podium's file menu. Note that in this case, compiling a file does not imply loading its code too. So you need to compile load it. Compiled files are of type .fsl. you can mix these with definitions typed directly into the listener. Lisp doesn't care, but make sure you have saved everything at the end of the day.



Dear Dr Levine,

How do I insert a newline into a function I'm messing with in the listener. Each time I type return it yanks the whole thing down to the prompt. It's getting annoying.

Yours, Annoyed.

Dear Annoyed,

In the listener, Return is bound to the editor command "Execute or Insert Newline or Yank from Previous Prompt" (igh). What you probably wanted was Control-O (letter O not digit 0) which stands for "Open Line". It inserts a newline into the buffer without moving anything anywhere.



Dear Dr Levine,

I wish to cultivate your suggestions for becoming a lazy typist. Can you remind me how it's done?

Yours, Slothful.

Dear Slothful,

What a good idea. Type Alt-Control-I to complete a symbol by comparing what you've typed with all the symbols in memory. Type Alt-/ to complete by looking backwards up the current window.



Dear Dr Levine,

Although it doesn't signal any errors, my code still doesn't do what I want it to? How do I fix it?

Yours, Broken

Dear Broken,

The macros trace and untrace , and the function break will all be of interest to you. Chapter 5 of the "LispWorks User Guide" will be of great use, but the basic idea is that if you trace a function, then every time it is called and every time it returns, you get a line of output in your listener to tell you about it. If the function returns abnormally (e.g by throwing - which we haven't covered yet - or by you aborting from an error), the trace output will say "Throwing".

Function break takes a format string (and format arguments if the string wants them). You insert the function in your code. When it's called, it uses the format information to print a message to the listener, then it enters a debugging loop.

CL-USER 29 > (defun foo (x)

(if (> x 5)

(progn

(break "Hello, x is ~a." x)

(1- x))

(1+ (foo (+ x 2)))))

FOO CL-USER 30 > (trace foo)

(FOO) CL-USER 31 > (foo -8)

0 FOO > (-8)

1 FOO > (-6)

2 FOO > (-4)

3 FOO > (-2)

4 FOO > (0)

5 FOO > (2)

6 FOO > (4)

7 FOO > (6) Hello, x is 6.

1 (continue) Return from break.

2 (abort) Return to level 0.

3 Return to top loop level 0. Type :b for backtrace, :c <option number> to proceed, or :? for other options CL-USER 32 : 1 > :c

7 FOO < (5)

6 FOO < (6)

5 FOO < (7)

4 FOO < (8)

3 FOO < (9)

2 FOO < (10)

1 FOO < (11)

0 FOO < (12)

12 CL-USER 33 >

Dear Jagged,

To indent one line of code, use the Tab key. You do not need to be at the start of the line to get this to work.

To indent a whole lisp form (eg a whole defun) click on the opening left parenthesis and use the key combination Alt-Control-Q.

Dear Dr Levine,

How do I tell whether a function is defined or not? How do I tell if it's a Common Lisp function or one of yours / mine?

Yours, Scatty

Dear Scatty,

To find out whether a symbol is defined as a function or not, use fboundp :

(fboundp 'mapcar) => true

(fboundp 'rubbish) => nil

To find out whether it is a Common Lisp symbol, use symbol-package :

(symbol-package 'defun) => #<PACKAGE COMMON-LISP>

(symbol-package 'my-own-junk) => #<PACKAGE COMMON-LISP-USER>

To find out whether it's a macro or a function, use macro-function :

(macro-function 'mapcar) => nil

(macro-function 'defun) => true

Similarly, special-operator-p will tell you whether a symbol is defined to be a special operator.



Dear Dr Levine,

How will I ever learn to use all the flash features in the Editor?

Yours, Keycode.

Dear Keycode,

I suppose the lazy (from my point of view) answer is to suggest you look in the "Editor User Guide"! A quick flick through chapter 2 may be enough. If you want to know (say) all the commands to do with moving Backwards, use the key combination Control-H A, then type the word backwards to the prompt, and see what you get.

