2011-12-07

Xmas wish: generate depends.mk from .asd file

Touting a little Xmas wish into the snowy intertubes: Many kudos to anyone who writes a little tool to generate a depends.mk Makefile from an .asd file. (Similar to gcc's -M / -MM flags.)

2011-12-01

A Conditional Situations Function API Pattern

I haven't written for a long time, and before Zach is going to weep my occasional mumblings from Planet Lisp, I thought I better sit down and share some API pattern that I have grown fond of.

The pattern addresses conditional code paths in a function's execution, in particular exceptional situations. Typically, there are the following ways you want to deal with a conditional situation:
  • return a caller-specific value,
  • signal an error as a structured way to transfer control,
  • signal a warning or log a message and continue execution,
  • signal a warning or log a message and return from execution,
  • ignore the conditional situation and just continue execution,
  • or perform some arbitrary caller-specific action.
Using the pattern, we will be able to express all those ways conveniently and concisely in the call to the function.

As illustrative example throughout this posting, we will use JOIN-THREAD. (It was the recent update of SBCL's JOIN-THREAD that reminded me on this pattern.)

JOIN-THREAD waits until the passed thread finishes its execution and returns the values of evaluating the last form in the thread. There are two exceptional situations involved:
  1. as one does not necessarily want to wait forever, a caller can specify a timeout that might expire;
  2. the thread might not have finished gracefully.
The pattern I want to introduce would make it have the following function interface:
(join-thread thread &key timeout on-timeout on-failure)
Where ON-TIMEOUT and ON-FAILURE can be either functions taking a condition object, or a non-function value that would essentially be interpreted as if (CONSTANTLY <the-value>) was passed.

The code invoking the ON-TIMEOUT callback might be written as follows:
(if (functionp on-timeout)
(return-from join-thread (funcall on-timeout <timeout condition>))
(return-from join-thread on-timeout))
Notice that the callback is invoked with a Condition object. Notice further that it's invoked in a tail position of the function being defined. This is true for exceptional situations; in the broader case of conditional situations, the function will usually continue further after having invoked the callback. (Passing a non-function value should result in returning that value even in the case of a mere conditional situations; it makes writing tests much easier that purport to exercise exactly that code path.)

Despite being an exceptional situation (i.e. just continuing is usually impossible), we might still want to provide the caller the ability to proceed further by using Common Lisp's restart system. E.g. to allow a caller to just plainly continue and hang on waiting on the thread forever, we could have written:
(if (functionp on-timeout)
(with-simple-restart (continue "Ignore timeout, hang on thread ~S." thread)
(return-from join-thread (funcall on-timeout <timeout condition>)))
(return-from join-thread on-timeout))
And we can already express a variety of different behaviours. To simply return :TIMEOUT when the timeout expires, we call JOIN-THREAD as follows:
(join-thread <thread> ... :on-timeout ':timeout)
To signal an error on timeout, we call JOIN-THREAD as follows:
(join-thread <thread> ... :on-timeout #'error) ; this should probably be the default
To turn the timeout into a mere warning, it is unfortunately not enough to simply pass #'WARN because WARN is specified to require a condition of subtype Warning.
(join-thread <thread> ... :on-timeout #'warn)  ; caveat: won't do
This restriction on WARN is superfluous but it's there, and we can always define our own variant:
(declaim (inline alert))
(defun alert (datum &rest args)
(let ((condition (apply #'coerce-to-condition datum args)))
(if (not (typep condition 'warning))
(cl:warn "~A" condition)
(cl:warn condition))))

(join-thread <thread> ... :on-timeout #'alert)
Notice that the above call will display a message on timeout and return NIL. To display a message (or log it using some arbitrary log mechanism) and go on waiting, we could use the following functions:
(declaim (inline invoke-and-continue))
(defun invoke-and-continue (function condition)
(funcall function condition)
(continue condition)
(error "BUG: could not find a CONTINUE restart for condition ~S." condition))

(defun alert+continue (condition)
(invoke-and-continue #'alert condition))

(defun logg+continue (condition)
(invoke-and-continue #'logg condition))

(join-thread <thread> ... :on-timeout #'alert+continue)
(join-thread <thread> ... :on-timeout #'logg+continue)
Another example would be ALERT+RESIGNAL which will resignal the condition. This can be useful during debugging when you want to display a condition's underlying message stemming from a certain function call that a handler higher up might catch -- just add :ON-TIMEOUT #'ALERT+RESIGNAL to the call.

If desired, one could add
(defvar *timeout-behaviour* #'error)
(defvar *failure-behaviour* #'error)
and make :ON-TIMEOUT and :ON-FAILURE default to these variables.

So what's nice about this pattern?

After all the CL equivalent would be
(handler-bind ((timeout #'alert+continue))
(join-thread <thread> ...))
or
(handler-case (join-thread <thread> ...)
(timeout () :timeout))
which may not be as concise but surely is not overly verbose either.

A couple of things.

For one, it's essentially Continuation Passing Style for exceptional situations which can be exactly what you want occasionally. Also the return-a-value case does not involve signaling a condition or an extra function call - which can make a difference. Likewise, handling an exceptional situation does not involve a non-local exit; just a function call and a local exit.

And another thing, it serves as a window of opportunity to document the exceptional situations in the function's docstring, and of course, it helps remembering these situations during automatic lambda list display.

And it's easier to change between different behaviours as it does not require changing a HANDLER-BIND to a HANDLER-CASE or vice versa, or having to add a BLOCK for explicit transfer of control out of a handler.

And, as mentioned before, the conciseness of the return-a-value case is very handy when writing tests.

It also makes code read more like prose. (He said, handwavingly^Wsternly.)

2011-03-27

Use case for Restart-Bind

It's always a good day when you find a perfect use case for one Common
Lisp's less used operators. Lately I had the pleasure to find a good
opportunity for RESTART-BIND.

I've written a network simulator in a couple of hundreds lines of
Common Lisp (not counting our basic protocol and miscanellous stack)
to emulate mobile IP networks. We use it to review that our mobile
broadband accelerator
is behaving the way we want it to behave. We
also use it in a complete virtual setup using UML instances for our
test suite as well as for the lab in our office.

For determinism purposes I wanted to be able to reseed the
*RANDOM-STATE* to its initial value by some means. And it turned out
that RESTART-BIND is just the right thing for that job:
(defun simulator (... &key (seed #xDEADBEEF) ...)
(let ((*random-state* (sb-ext:seed-random-state seed)))
(restart-bind
((reseed #'(lambda ()
(setf *random-state* (sb-ext:seed-random-state seed)))
:report-function
(formatter "Reseed *RANDOM-STATE* with initial :SEED value.")))
...)))
You can reseed manually by interrupting the network simulator and
using the RESEED restart, or you can reseed programmatically (e.g.
periodically after a certain time of inactivity) by

(invoke-restart 'reseed)

Can you feel that warm and fuzzy feeling? Just the right thing. :-)

PS.

Other fun note about restarts and RESTART-BIND. If you squint your
eyes, you will discover that restarts are essentially nothing else
than dynamically scoped local functions, and RESTART-BIND is basically
DYNAMIC-FLET.

2010-08-08

What I'm up to lately

Long time no update.

For the last few months I've become rather silent not only on the planet.lisp blogosphere but pretty much on the whole Common Lisp open source world. The reason for that is that since the beginning of the year I've become proud part of a hot telecom startup. Right after having had a big rush to finish my bachelor thesis in one go.

I've spent the last three months hacking in Malaysia, mostly in Kuala Lumpur, though sugared with occasional visits to tropical islands to keep sanity above a reasonable threshold. I now just arrived on the West coast of Sweden (reasonably close by to Gothenborg) where we're going to spend the next month at as we're told August to be lovely around there.

You bet what we're hacking in. Yes, that's right, we're doing funky TCP/IP related optimization and analysis in that dead, slow language. And I can tell you it's marvellous! It's a whole different experience if you can just make use of the language without being constrained like you usually are when developing open source libraries. We don't have to try to keep the number of dependencies small. We don't have to care about package name collisions. For example, we have a package named FMT containing functions to be used in format strings via ~/FMT:FOO/. Common Lisp is definitively a very nice language for actual product development. And it shows that is has been used for that while it was designed.

Of course, there's more that makes my time so incredibly marvellous: having pleasure to work with bright and, I think, famous guys, like that pseudo-german hacker poster boy Luke Gorrie, the omniscient Stelian Ionescu, homeless dude Ties Stuij of stix.to fame, the Erlang celebrity Sean Hinde, business genius Jane Walerud, and That Clever Statistics Guy. Also seeing different parts of the world, meeting kind people of different cultures, and developing sellable products and thus having customers to care about.

Fun.

Lots of it!

2010-03-06

Slime tidbits (2010-03-06): Slime & ECL

Together with Juan Jose Garcia-Ripoll, I worked on improving the integration of ECL into Slime.

He did a tremendous job on the ECL side adding all the stuff that's needed for a well-working swank backend, so if you're going to try out ECL with Slime, and are pleasantly surprised, please direct most of the gratitude towards him.

I threw out backwards compatibility, and you really have to get the 10.3.1 release otherwise the CVS of Slime will refuse to compile. There's no point in artificially maintaining backwards compatibility for something which barely worked.

Most noteworthy is the fact that you can now M-. all the way down, that is not just into the Lisp source base of ECL, but also into the C source base. And because it's based on TAGS file, M-. (and M-*) will continue to work once in a .c file. For illustration, I created an animated screenshot. (Blogspot seems to convert uploaded images into the PNG format which is the reason that I have to externally link to animated gifs rather than include them into by blog posting proper.)

There's of course still stuff to do:
  • storing arglist information for user-written functions
  • storing source-location information for each method of a gf
  • introspection into C objects
Especially the last thing would be rather cool. And while I think the first two items are on Juanjo's agenda, the last item needs some brave hero looking for fame and glory. In case you want to volunteer, drop a mail to the ECL mailing list!

2010-03-05

Slime tidbits (2010-03-05)

In December 2009, Stas Boukarev and myself added some really cool stuff to the slime-asdf contrib, and while I've always wanted to blog about it, I just haven't come around doing so.
  • M-x slime-load-system (,load-system): Compile and load an ASDF system; that command currently hooks into the Slime compilation-notes machinery, so compilation notes, warnings, etc. will be collected and will end up in the *SLIME Compilation* buffer. This command has always been there, I just mention it for sake of completeness.
  • M-x slime-open-system (,open-system): Open all the files specified in the system.
  • M-x slime-isearch-system and M-x slime-rgrep-system: Run the command isearch and rgrep respectively on all the files specified in a system. That is particularly useful if slime-edit-definitions (M-.) and slime-edit-uses (M-?) won't do.

    In case of slime-rgrep-system, the commands next-error and previous-error will jump through the matches in the *grep* buffer. I bound those commands to F11 and F12, though by default they're also bound to M-g p and M-g n (also C-x `).
  • M-x slime-query-replace-system: Poor man's refactoring tool; run query-replace on all the specified files in a system. See this animated screenshot for an exemplary run. (Animated gif was generated on behalf of Zach Beane's Skippy library!)
  • M-x slime-query-replace-system-and-dependents: Like the former function, but also run query-replace on all the files of all systems depending on the user-queried system.
The latter two functions are really useful if you're past the initial state of something -- your system already grew to multiple files -- but still away from finishing and so you often want to rename identifier and slightly change APIs.

2009-11-12

Munich Lisp Talk, 10th November 2009

Last Tuesday, I gave short talk about a library I have been writing on: Sequence Iterators.
The library is perhaps a bit misnamed because at the moment, it's really a convenience layer on top of iterators. It's supposed to provide tools to make writing functions that operate on sequences convenient, and yet not blatantly inefficient.

I'd be very much interested in feedback regarding rough corners if you find a case to apply the library. If you want to give it a shot, there's a file "more-sequence-functions.lisp" which contain prototypes of useful sequence function for which I haven't yet had the time to write them.

Please notice that the library is still work in progress.

2009-10-31

Looking for a Lisp project?

You're an intermediate to the Common Lisp language and are desperately looking for a practical project to try your Lisp skills at? You're longing for fame and glory?

If that's the case, I have something for you:
  1. write a library to access the Web API provided by launchpad,
  2. afterwards, using that library, make it possible to conveniently add and update tickets in a (not yet existing) bug tracker for clbuild. The tickets are supposed to add/update repository urls.
Sounds interesting? If so, drop me a mail.

2009-10-24

SLIME tidbits (2009-10-24)

  • To quickly find out the "revision" of your slime checkout, you can now use M-x slime-changelog-date.
  • Sometimes, e.g. due to character encoding confusion, the Emacs side of Slime can be brought to a dysfunctional state. M-x slime-reset will hopefully get you back to business.
  • Restarts as shown in the Slime Debugger are now numbered reversely. The advantage is that often-existing restarts will now very likely get associated with the same number as you can see on the screenshot below. (Remember that the numeric keys are mapped to invoke the corresponding restarts.) This may mean that you have to invalidate some of your muscle memory -- notice that often-needed restarts do come with a static, symbolic mapping, i.e. q to abort to toplevel, a to invoke the most recently established abort restart, and c to invoke a continue restart.

  • Commands which open an Xref buffer (in particular M-?) do not select that buffer anymore. Instead, you're now supposed to use the commands C-M-. and C-M-, to cycle through the entries in the Xref buffer from within your source buffer. That's more ergonomic from my experience. The intended key sequence is: M-? C-M-. C-x 1 frob C-M-. C-x 1 frob etc.

2009-10-21

SLIME tidbits (2009-10-21)

Stas Boukarev just comitted two useful new commands to CVS: slime-open-system, and slime-browse-system.


As you can see on the above screenshot, M-x slime-open-system, or alternatively the REPL shortcut ,open-system, will open all the files listed in a system's .asd file. Optionally, it'll also load the system if it's not already loaded.

And on the screenshot below, you can see M-x slime-browse-system (or ,browse-system at the REPL, respectively) which will open the directory a system's .asd file lays in using dired.

2009-10-18

#0AFFFF

Common Lisp is a wonderfully complex language, and probably no matter how long you've been studying it, you'll always find a thing you didn't know before.

What, for example, do you think #0AFFFF represents?

Perhaps you're thinking of the color turquoise represented as a hexadecimal RGB value?

Well, witness for yourself:
CL-USER> (setf *read-base* 16)
16

CL-USER> #0AFFFF
#0A65535
(Bonus point if you know how to restore *READ-BASE* to a value of 10 again.)

Still no idea?
CL-USER> (type-of *)
(SIMPLE-ARRAY T NIL)
Right, #0AFOO is literal syntax for (make-array nil :initial-element 'foo).

And, yeah, even though Common Lisp is surely a complex beast, it's at the same time very well engineered. Witness thus:
CL-USER> (defvar *a*
           (make-array nil :initial-element 41))
*A*
CL-USER> (incf (aref *a*))
42
CL-USER> *a*
#0A42
And if you want to see really quirky stuff, take a look at strings with an element-type of nil.

2009-10-10

ANN: Named-Readtables 0.9

The editor-hints project is pleased to announce Named-Readtables.

What are Named-Readtables?

It's a library a) to help you to organize your readtable hacks, and b) to help your development environment to deal with these hacks. For detailed information see What are Named-Readtables? in the documentation.

Foretaste

DEFREADTABLE (analogously to DEFPACKAGE) can be used to specify the content of a readtable.

IN-READTABLE (analogously to IN-PACKAGE) can be used to specify what readtable should be used while compiling a .lisp file.

Named-Readtables has an API very much inspired by the existing API of packages. But see Important API idiosyncrasies in the documentation.

Documentation


See here.

Download

darcs get http://common-lisp.net/project/editor-hints/darcs/named-readtables/

Release Notes


The release was tagged as 0.9 even though it's actually pretty much a 1.0. Experience tells that no matter how much you try to polish a piece of software, there will be two to three issues. The 1.0 will wait for these issues be reported.

Implementations

The library has been tested on SBCL, CCL, Clisp, ABCL (head), ECL, Allegro 8.1, Lispworks 5.1.

2009-09-21

Slime-sprof

Stas Boukarev polished up Juho Snellman's slime patch which nicely integrates SBCL's statistical profiler into Slime, turned it into a proper contrib (slime-sprof) and committed it to CVS. The patch dates back as far as 2005, with an update in 2006, and I'm glad that it eventually turned up into Slime itself.

Here's the link to the documentation explaining how to use it.

Thanks Juho and Stas!

  • Up-to-date screenshot by Stas:


  • Earlier screenshot by Juho:

2009-09-20

SLIME tidbits (2009-09-20)

Today I'll write about a very recent new addition: slime-edit-uses bound to the keys M-? and M-_.

It is the logical counterpart to slime-edit-definition (M-.) .

Basically, it's nothing more than a wrapper around the already existing Xref commands (slime-who-calls, etc.) but it's a pleasure to use because a) it's just one key binding which does all instead of a multitude of different special-purpose bindings, and b) it's an easy binding (M-? vs. C-c C-w KEY) and obvious as well (right next to M-. its counterpart.)

What does it do? Well see for yourself:

  • on functions, it'll show a list of all call sites.
  • on macros, it'll show a list of the sites the macro is expanded.
  • on special variables, it'll list all the places the variable is set, bound, or referenced.
  • on classes, it'll show a list of methods that specialize on that class. (no screenshot)
Of course, the usual disclaimer applies: The quality of this feature highly depends on how much Xref information your implementation is able to store.

Now, for me this begets the following question: How easy would it be to make SBCL collect Xref data during the build of itself?

2009-09-05

WANTED: trivial without-package-locks

Has anyone written a trivial wrapper definition for WITHOUT-PACKAGE-LOCKS ?

"Trivial" as in trivial-utf8, trivial-backtrace, trivial-garbage, trivial-shell, trivial-timeout, et cetera perge perge.

2009-07-25

Common Lisp & Vim

Nagging about how preposterous it is to be forced to learn Emacs, is no more.

Frank Duncan has been working on Nekthuth, a Vim plugin for Common Lisp. While it's not completely prime time right now, it certainly looks very promising. Definitively, the most feature-full plugin I've seen so far.

Now if you're one of those few lost souls who just do not want to find absolution in the Church of Emacs, take a look at it and give Frank a hand, or two. For example, make it use Slime's SWANK-BACKEND, not the server, just the portability layer.

Alternatives: Cusp, a plugin for Eclipse. ABLE, a standalone text editor written in Common Lisp.

2009-06-20

Erik Naggum, RIP.

It's sad but seems to be true: Erik Naggum was found dead in his home.

Last September, I wrote him a mail to thank him for the wealth of postings
he had contributed to comp.lang.lisp and for the impact they had on me.
I now feel incredibly glad I did that as I had always postponed doing so
for years.

Following is his response.

RIP, Erik.



* Tobias C. Rittweiler (2008-09-19 00:37)
> for a long time I've wanted to send an e-mail to express the
> gratitude I feel for the countless usenet postings that you have
> written in your comp.lang.lisp history. Now I finally came around
> doing so:

It’s been quite a while since I posted my last article to c.l.l, but
very warm and welcome messages like yours still keep coming in at a
rate of about one a week. It amazes me.

> Thank you for the time and energy you spent in writing so many
> sophisticated and thought-provocating articles. I never understood
> where you drew this massive amount of energy and the will to
> continue from, considering the feedback you received back at that
> time.

Even when I was posting at a high rate, I received more mail from
those who appreciated what I had posted. I needed that encouragement
and knowing that despite the increasing amount of insanity on the
newsgroup, lots of people were reading what I wrote with a positive
attitude. However, there are some people whose evil ways are truly
destructive, and those are the moralists and the punishers who are
utterly unable to produce anything good at all, but all the more
hell-bent on making others pay for such things as not living up to
their expectations, doing what they think is right, etc, and I drew a
considerable amount of energy from my life-long desire to rid the
planet of moralists and punishers. It may sound contradictory, but I
hold that the use of force and violence and the lesser evils of
moralizing and punishment should only be used to prevent any of them,
never to seek any other goal: Telling a moralist that moralizing is
wrong, punishing those who punish others, using force and violence to
stop those who initiate the use of force and violence — you get the
picture — is the right thing to do. Unfortunately, this gets the
moralizers and punishers all worked up, and they prove that they
really are the psychopaths they only appeared to be when someone had
the gall to do something against /their/ desires. So even though my
general outlook on life went under-appreciated, namely that if you
know what other people should have done in the past, you never have
any clue what you or anyone else ought to do in the future, and if you
are concerned with what you yourself ought to do in the future, you
generally leave other people alone to figure out what /they/ ought to do
in the future, too, lots of people picked up on the positive message:
Exposing moralists and punishers for what they really are —
psychopaths — does a great service to any community who suffers from
their pernicious effects. Of course, if you are a horribly bad person
like that, you can only see others as reflections of yourself, and you
never understand why anyone would want to moralize against or punish
/you/, because part and parcel of being rabidly insane is never being
able to see yourself from the outside, and you think insane thoughts
like “How /dare/ anyone moralize against or punish /me/, when I‘m the sole
moral authority in the whole Universe and everyone, everywhere have a
moral duty to behave the way /I/ tell them!”. Or, in other words, people
who partition the world population into “the good” and “the bad”
always make the mistake of believing that they fall into the “the
good” partition, when they are actually among the very few that are
truly evil: No monumental evil act in the history of mankind has been
committed by anyone who thought of themselves as “evil” — on the
contrary, the worse the (objective) evil, the more the perpetrator was
completely convinced of the goodness of himself and of his
“purification”. So when the newsgroup became plagued by the evil kind
of moron that has nothing to contributed and no rewards for anyone
doing the right thing, but only harm and punishment for those who do
the wrong thing in their eyes, it was time to quit. Had I had even
more energy, I could have stayed, but I had ran out of steam fighting
false accusations, which is another one of those hallmarks of truly
evil people who think nothing of harming the innocent in their crusade
against the “evildoers”. It turns out, as any study of history will
show, that those accused by moralists and punishers are always
innocent. That’s why we need courts, so those who accuse are not the
ones to decide on the guilt and the punishment. Stupid people tend not
to grasp this fact, and only see courts as means of letting people
they “know” are guilty avoid punishment.

> And I particularly mean your non-technical contributions. I read all
> those now already several years ago when I was sixteen if I'm
> remembering correctly. I recall how I was shocked at the tone you
> used, and the aggression you seemed to feel towards people, as I
> grew up in feel-good communities myself. [The postings] made me value
> technical expertise and competence over civil masquerade, and they
> revealed how the latter can sometimes even impair the communication
> for the former.

Civility and politeness are extremely useful tools in communication
with people who are more wrong than right, but of very little use with
people who are vastly more right than wrong. This counter-intuitive
observation comes directly from the fact that we simply do not need
civil and polite ways of telling people that they are right about
something. So the people who have most to gain from civility and
politeness are people who know they are and intend to /stay/ wrong while
they force everybody else hold their tongues. That may have been a
very good way of building societies before /anyone/ was usually right
about anything. It is only in the twentieth century that a sizable
fraction of the population had any means to know whether they were in
the right or in the wrong to begin with. Before we invented the
concept of the real world, everybody lived their entire lives in their
own emotional world. After science and technology invented the concept
of the real world and of truth as correspondence between thoughts and
reality, the internal, private world turned out to be /untrue/ almost
all the time. These days, I keep telling people that you only /really/
grow up and become a human being (as opposed to a mere animal) when
you realize that most of what you think and almost all you feel is
/wrong/ and every person, however smart or highly esteemed by their
peers, is utterly and completely incapable of determining where they
are right among all this wrongness on their own. We tend to believe we
are mostly right, however, and only notice when the consequences of
our actions contradict our best expectations. Now, there are many
areas of life where there /is/ no way to sort right from wrong, and it
would certainly be impolite to point out an error that was only
relative to our own personal values, which is where the impoliteness
of moralizing comes in, but modern man enjoys a growing number of
areas where we can unequivocally sort right from wrong, and then it is
impolite /not/ to point out an error, for that means we let someone
believe something that will cause them harm, or at least undesired
consequences, later on. This means that in the areas of life where
people are mostly wrong, it is indeed a good thing to be civil and
polite all the time, as one wouldn’t want others constantly to point
out one’s own mistakes, either, but in the many areas where it is
possible to be right, and positively harmful to be wrong, allowing
people to hold on to false beliefs in order to protect their feelings
is really, really bad for everyone. The key, therefore, is knowing
which areas can and which still cannot tell right from wrong. It is my
firm position that no areas of science, technology, engineering,
mathematics, and allied disciplines such as medicine, are proper
arenas for politeness and civility. If people are wrong and are
spreading dis- or misinformation in these fields, everybody hurts
because it becomes that much harder to know right from wrong. However,
in areas where no one can really tell, such as ethics, politics,
fashion, etc, even though we may have pretty good ideas and
communities who /choose/ a particular set of beliefs, it behooves people
to be humble and civil and polite because fighting with people who are
wrong, but believe they are right, yet there are no means to prove
that, would be extremely tiresome, as it became on c.l.l when people
who stopped thinking about issues where we /can/ decide right from
wrong, started to bother everyone with their /personal/ problems when
others disagreed with them.

> In retrospect, I'm pretty sure that you helped me become the
> individuum I am now.

I’m very pleased to hear that, and particularly that you took the time
to write and tell me. I wish you the best of luck for the future!

Best regards, Erik Naggum
--
Member of AAAI AAAS ACM AMS APS ASA ASL IEEE IMS MAA NYAS PSA SIAM USENIX
The United States of America still symbolizes individualism, rationality,
and intellectual achievement to me — even though most Americans disagree.

2009-05-14

SLIME tidbits (2009-05-14)

First a small addendum: In my previous blog entry I demonstrated the improved font-lock magic in Slime to shadow forms suppressed by reader conditionals. Anyone who succumbed to the temptation and updated their Slime checkout, should really update to today's HEAD. There has been a couple of issues which have been fixed meanwhile.

In this blog posting I'll demonstrate my work on Slime's inspector for STANDARD-OBJECTs. Previously it looked like this:

I always found the [set value] and [make unbound]buttons after each slot entry pretty distracting, if not to say annoying. So I spent some time to replace them with a checklist as follows:

Quite cool that you can do this with Slime's inspector! Notice that I did not have to touch a single Elisp code line for all this.

You may have noticed the new [group slots by inheritance] button: by default the slots are sorted alphabetically by their name. After pressing this button, however, the slots will be grouped according to the class they were inherited from. Or in CLOS terminology: according to the class they're direct slots of.

2009-05-02

SLIME tidbits (2009-05-02)

Since a long time SLIME tries to highlight forms specially that are suppressed due to reader conditionals. That feature has never worked reliably for me; sometimes such forms were highlighted, but most often not. And even if they were highlighted, redisplay (or rather refontification) would often remove the highlighting again.

While resuming to work on my named-readtables library -- which includes a little bit of portability glue --, I became annoyed^W intrigued enough to take a look at the cause of this non-deterministic behaviour.

The issue took more effort than I'd have initially expected. But as you can see from the screen shot, it should be fixed now. It shows the FINALIZE function from the trivial-garbage project. (I hope planet.lisp reader will be able to see the image, too.)

2009-01-03

SLIME tidbits (2009-01-03)

  • When you update to HEAD make sure you enable the slime-repl contrib, otherwise you'll be stuck to an old-school inferior-lisp REPL, only.
    Recommended: Use the slime-fancy meta contrib which enables various useful features you'll probably enjoy.
  • C-u C-c C-c will compile the defun at point with maximum debug optimization setting. (SBCL only so far.)
  • Bleeding edge feature: M-- C-c C-c will compile the defun at point with maximum speed optimization setting (still SBCL only.) This is very useful to benefit from SBCL's type inference and elicit compiler notes.