Duck and cover! Another mini-series approaching!
My apologies to users of CoCreate Modeling
who tried to find some meat for them in the package riddle
series for them - there wasn't any, as that series was strictly meant for 
Lisp geeks. Sorry!
This new series covers programming fundamentals as well.
If you ever wanted to understand how Common Lisp functions like print and
CoCreate Modeling commands such as extrude differ and how they
interact, you've come to the right place.
Reader highway45 recently came up with a 
very interesting observation (abridged and translated from German):
Usually, I call a dialog like this: (set_pers_context "Toolbox-Context" function)
Or like this:
function
As soon as I add parentheses, however, the "ok action" will be called:
(function)

When highway45 talks of "functions" here, he actually means commands like 
extrude or 
turn. So, 
(set_pers_context "Toolbox-Context" extrude)? Really? Wow!
set_pers_context is an internal CoCreate Modeling function dealing with
how UI elements for a given command are displayed and where. I was floored -
first, by the fact that an end user found a need to call an internal function like this, 
and second, because that magic incantation indeed works "as advertised" by highway45. 
For example, try entering the following in CoCreate Modeling's user input line:
(set_pers_context "Toolbox-Context" extrude)
Lo and behold, this will indeed open the 
Extrude dialog, and CoCreate Modeling
now prompts for more input, such as extrusion distances or angles.
What's so surprising about this, you ask? If you've used CoCreate Modeling for a while,
then you'll know that, as a rule of thumb, code enclosed in parentheses won't prompt
for more input, but will instead expect additional parameters in the command line itself.
For example, if you run 
(extrude) (with parentheses!) from the user input line, Lisp will 
complain that the parameter "DISTANCE is not specified". But in highway45's example, there 
clearly 
was a closing parenthesis after 
extrude, and yet the Extrude command started to 
prompt!
So is 
set_pers_context some kind of magic potion? Try this:
  (print extrude)
The Extrude dialog opens and prompts for input! Seems like even 
print has
magic powers, even though it's a plain ol' 
Common Lisp standard function!
Well, maybe there is something special about all built-in functions? Let's test this out and
try a trivial function of our own:
  (defun foobar() 42)
  (foobar extrude)
Once more, the dialog opens and awaits user input!
So 
maybe it is neither of 
set_pers_context, 
print or 
foobar that is magic - but instead 
extrude. 
We'll tumble down that rabbit hole next time.
To be continued...
I'll bore you just one more time with this: When executing (test) as defined
in the following code, Lisp claimed that the function #:TEST_DIALOG is undefined.
(defun test()
  (test_dialog))
(in-package :clausbrod.de)
(use-package :oli)
(sd-defdialog 'test_dialog
  :ok-action '(display "test_dialog"))
In 
part 3 of this mini-series,
we figured out that the 
#: prefix indicates an 
uninterned symbol - and now
we can solve the puzzle!
Earlier, I had indicated that 
sd-defdialog automatically exports dialog
names into the default package. To perform this trick, somewhere in the bowels of
the 
sd-defdialog macro, the following code is generated and executed:
(shadowing-import ',name :cl-user)  ;; import dialog name into cl-user package
(export ',name)                     ;; export dialog name in current package
(import ',name :oli)                ;; import dialog name into oli package
(export ',name :oli)                ;; export dialog name from the oli package
As a consequence, the dialog's name is now visible in three packages:
-  The default package (cl-user)
-  Our Lisp API package (oli)
-  The package in which the dialog was defined (here: clausbrod.de)
This is quite convenient for CoCreate Modeling users - typically
mechanical engineers, not Lisp programmers. They don't want to deal with the 
intricacies of Lisp's package handling, but instead simply assume that the 
command (dialog) will be at their disposal whenever they need it.
Let's look up what the Common Lisp standard has to say on
shadowing-import:
shadowing-import inserts each of symbols into package as an internal symbol, regardless of whether another symbol of the same name is shadowed by this action. If a different symbol of the same name is already present in package, that symbol is first uninterned from package.
That's our answer! With this newly-acquired knowledge, let's go through our 
code example one more and final time:
(defun test()
  (test_dialog))
Upon loading this code, the Lisp reader will intern a symbol 
called 
test_dialog into the current (default) package. As 
test_dialog has not
been defined yet, the symbol 
test_dialog does not have a value; it's just
a placeholder for things to come.
(in-package :clausbrod.de)
(use-package :oli)
We're no longer in the default package, and can freely use 
oli:sd-defdialog without
a package prefix.
(sd-defdialog 'test_dialog
  :ok-action '(display "test_dialog"))
sd-defdialog performs 
(shadowing-import 'test_dialog :cl-user),
thereby shadowing (hiding) 
and uninterning the previously interned 
test_dialog symbol.
Until we re-evaluate the definition for 
(test), it will still refer to the
old definition of the symbol 
test_dialog, which - by now - is a) still without
a value and b) uninterned, i.e. homeless.
Lessons learned:
-  Pay attention to the exact wording of Lisp error messages.
-  The Common Lisp standard is your friend.
-  Those Lisp package problems can be pesky critters.
The good news: If you follow a few rules of thumb, you'll probably never run into 
complex package problems like this. One such simple rule is to define your 
functions first before referring to them. So in our code example, defining
the dialog first before loading/defining the 
(test) function would have saved
us all that hassle.
Phew.
The other day, I finally bought Peter Norvig's classic
Paradigms of Artificial Intelligence Programming,
which everybody in the Lisp community seems to be raving about.
No book review yet, as I haven't even started to read the book. However, a while ago,
I worked through 
Norvig's implementation of the loop macro,
and ever since then, I knew I had to buy the book. The code contains a good amount of
Lisp macrology, and yet it is clear, concise, and so easy to follow. You can read it
like a novel, from cover to back, while sipping from a glass of 
pinot noir. 
Impressive work.
If you've soaked up enough
Common Lisp to roughly know what 
lambda and 
defmacro do, this is the kind of
code you should be reading to take the next step in understanding Lisp. This is also
a brilliant way to learn how to use 
loop, by the way.
I can't wait to find out what the rest of the book is like!
Update 9/2013: Norvig's (How to Write a (Lisp) Interpreter (in Python))
is just as readable and inspirational as the loop macro code. Highly recommended.
Lisp recently surprised me
with an error message which I had not expected.
(defun test()
  (test_dialog))
(in-package :clausbrod.de)
(use-package :oli)
(sd-defdialog 'test_dialog
  :ok-action '(display "test_dialog"))
Load the above code, run 
(test), and you'll get:
 
In CoCreate Modeling, the 
sd-defdialog macro automatically exports the name of the new
dialog (in this case, 
test_dialog) into the default package. Hence, you'd expect that
the function 
(test), which is in the default package, would be able to call that dialog!
Astute readers (and CoCreate Modeling's Lisp compiler) will rightfully scold me for using 
(in-package) in the midst of a file. However, the error doesn't go away if you split up
the above code example into two files, the second of which then properly
starts with 
(in-package). And in fact, the problem originally manifested itself in a 
multiple-file scenario. But to make it even easier for readers to run the test themselves,
I just folded the two files into one.
Lisp actually provides us with a subtle hint which I ignored so far: Did you notice 
that the complaint is about a symbol 
#:TEST_DIALOG, and not simply 
TEST_DIALOG? 
The 
#: prefix adds an important piece to the puzzle. Apparently, Lisp thinks 
that 
TEST_DIALOG is not a normal symbol,
but a so-called 
uninterned symbol. Uninterned symbols are symbols which don't 
belong to 
any Lisp package - they are homeless. For details:
Uninterned symbols are beasts which live in a slightly darker corner of Common Lisp, or 
at least you don't  run into them too often. And in our particular case, it isn't exactly obvious
how 
TEST_DIALOG turned into an uninterned symbol. We would have expected it to
be a symbol interned in the 
clausbrod.de package, which is where the dialog is defined!
Those who are still with me in this series will probably know where this is heading.
Anyway - 
next time, we'll finally 
solve the puzzle!
Yesterday, I presented some Lisp code
which puzzled me for a little while.
To recap, here's the test code again:
(defun test()
  (test_dialog))
(in-package :clausbrod.de)
(use-package :oli)
(sd-defdialog 'test_dialog
  :ok-action '(display "test_dialog"))
Here is what happens if you save this code into a file, then load the file into 
CoCreate Modeling and call the 
(test) function:
 "The function #:TEST_DIALOG is undefined"
"The function #:TEST_DIALOG is undefined"? Let's review the code so that you 
can understand why I found this behavior surprising.
First, you'll notice that the function 
test is defined in the default Lisp package.
After its definition, we switch into a different package (
clausbrod.de), in
which we then define a CoCreate Modeling dialog called 
test_dialog.
The 
(test) function attempts to call that dialog. If you've had any exposure with
other implementations of Lisp before, I'm sure you will say: "Well, 
of course the system
will complain that 
TEST_DIALOG is undefined! After all, you define it in package
clausbrod.de, but call it from the default package (where 
test is defined). 
This is trivial! Go read
The Complete Idiot's Guide to Common Lisp Packages
instead of wasting our time!"
To which I'd reply that 
sd-defdialog, for practical reasons I may go into in a future blog
post, actually makes dialogs visible in CoCreate Modeling's default package. And since
the function 
test is defined in the default package, it should therefore have
access to a symbol called 
test_dialog, and there shouldn't be any error messages, right?
To be continued...
The other day, I spent some time debugging a surprising issue in Lisp code written
for CoCreate Modeling. Turns out that the problem can be shrunk down to
only a few lines, and is actually quite instructive on how Lisp's packages work -
an ideal candidate for this blog!
So here is the innocent-looking code:
(defun test()
  (test_dialog))
(in-package :clausbrod.de)
(use-package :oli)
(sd-defdialog 'test_dialog
  :ok-action '(display "test_dialog"))

Copy/paste this code into a file called 
test.lsp, then load the 
file
into a fresh instance of CoCreate Modeling. Run the 
test function by entering 
(test) in
the user input line. Can you guess what happens now? Can you explain it?
To be continued...
Previous month: Click 
here.
to top