2016-06-15

Table of Contents

1. Preface

2. ECL's "what's going on"

3. Porting Lisp Games to Android with Embeddable Common Lisp, Part 1

4. Common Lisp implementations

5. Building various implementations

6. Portability libraries

1 Preface

Hello,

I've managed to assemble the fourth volume of the ECL Quarterly. As
always a bit off schedule but I hope you'll find it interesting.

This issue will revovle around ECL news, some current undertakings and
plans. Additionally we'll talk about Common Lisp implementations in
general and the portability layers. I believe it is important to keep
things portable. Why? Keep reading!

Lately we're working with David O'Toole on making support for ECL on
Android better. He wants to distribute his games on this platform and
was kind enough to write an article for ECL Quarterly. Thanks to his
work we've discovered various rough edges and bugs in ECL and gained
some invaluable insight into the cross compilation problems of Common
Lisp applications.

As the final remark - I've found some time to establish a proper RSS
subscription feed for ECL and ECL Quarterly. I hope that this
issue will finally land on the Planet Lisp - a well known Lisp-related
blog posts aggregator maintained by Zach Beane.

I want to thank for the valuable feedback and proofreading to many
people, especially Antoni Grzymała, Javier Olaechea, Michał Posta,
Ilya Khaprov and David O'Toole.

Have a nice lecture,



Daniel Kochmański ;; aka jackdaniel | TurtleWare

Poznań, Poland

June 2016

2 ECL's "what's going on"

I've added a milestone with a deadline for the ECL 16.1.3 release
with the bugs I want to fix. You may find it here. I'm very happy to
receive a lot of positive feedback, merge requests and awesome bug
reports. Thank you for that! :-)

Backporting CLOS changes from CLASP was successful but we won't
incorporate them in the main branch. The recently resurrected cl-bench
has shown that these changes impact performance and consing negatively
(check benchmarks). If you are curious about the changes, you may
checkout the branch feature-improve-clos in the repository.

I'm slowly working on the new documentation. This is very mundane
task which I'm not sure I'll be able to finish. Rewriting DocBook to
TexInfo and filling the missing parts is hard. I'm considering giving
up and improving the DocBook instead.

In the near future I plan to make a crowdfunding campaign to
improve support for cross-compilation, Android and Java
interoperability in order to boost development. More details will be
probably covered in the next Quarterly issue.

3 Porting Lisp Games to Android with Embeddable Common Lisp, Part 1

3.1 Introduction

Recently I ported my Common Lisp game engine "Xelf" to the Android
operating system using Embeddable Common Lisp.

Some work remains to be done before I can do a proper beta test
release, but ECL Quarterly provides a good opportunity to pause and
share the results thus far. This is the first part of a two-part
article. The focus of Part 2 will be on performance optimization,
testing, and user interface concerns.

Special thanks to Daniel Kochmański, 3-B, oGMo, and the rest of the
Lisp Games crew for their inspiration and assistance.

3.1.1 About the software

Xelf is a simple 2-D game engine written in Common Lisp. It is the
basis of all the games I have released since 2008, and can currently
be used with SBCL to deliver optimized standalone game executables for
GNU/Linux, MS Windows, and Mac OSX.

Xelf home page: http://xelf.me/

Xelf documentation: http://xelf.me/reference.html

I've also published a Git repository with all the work-in-progress
scripts, patches, and libraries needed to compile Xelf for Android
with Embeddable Common Lisp, OpenGL, and SDL.

Android build setup: https://gitlab.com/dto/ecl-android-games-src

Please note that this is a pre-alpha release and is mainly intended
for Common Lisp developers looking to get a head start in building an
Android game. Use with caution.

Xelf is not required; you can substitute your own Lisp libraries and
applications and just use the repo as a springboard.

I would like to add support for CL-SDL2 as well, both as a prelude to
porting Xelf to SDL 2.0, and as a way to help the majority who use SDL
2.0 for current projects.

3.2 Problems

3.2.1 Choosing an implementation

As I use only Free Software for my projects, I did not consider any
proprietary Lisps.

Steel Bank Common Lisp now runs on Android, but SBCL as a whole cannot
yet be loaded as a dynamic shared library. This is a show-stopper
because Android requires the entry point of a native application to be
in a shared library specially embedded in the app.

Xelf works very well with Clozure Common Lisp, but CCL's Android
support is not fully functional at present. So I've been quite happy
to discover Embeddable Common Lisp. Its technique of translating
Common Lisp into plain C has made integration with the Android NDK
toolchain relatively simple.

3.2.2 Cross-compilation

For performance reasons the Lisp stack (meaning LISPBUILDER-SDL,
CL-OPENGL, CFFI, Xelf, the game, and all their dependencies) must be
compiled to native ARM machine code and loaded as shared libraries.

There is a complication in this task as regards ECL. The latter
produces native code by translating Common Lisp into plain C, and then
invoking the C compiler. But the C compiler toolchain is not typically
present on Android, and building one that is properly configured for
this task has proved difficult so far.

Therefore we must cross-compile the entire Lisp stack. ECL's Android
build procedure already cross-compiles the Lisp contained in ECL, but
there were additional difficulties in compiling Lisp libraries which
I'll cover below in the "Solutions" section.

3.2.3 Legacy code

Xelf has improved a lot over time and gained new features, but is now
outdated in some respects. When I first wrote Xelf in the 2006-2007
period SDL 1.2 was current and OpenGL Immediate mode had not yet been
officially deprecated. This hasn't been a terrible problem in
practical terms, given that both are still widely supported on PC
platforms. But porting to Android would mean I could not procrastinate
any longer on updating Xelf's SDL and OpenGL support.

3.3 Solutions

3.3.1 CommanderGenius to the rescue

Help arrived for my SDL woes in the form of Sergii Pylypenko's
"CommanderGenius", a fancy port of SDL 1.2/2.0 to Android. I can
utilize the existing LISPBUILDER-SDL bindings for SDL, SDL-MIXER,
SDL-TTF, SDL-IMAGE, and SDL-GFX. Not only that, there are extra
features such as gamepad support, floating virtual joysticks, access
to touchscreen gesture data and Android system events, support for the
Android TV standard, and much more.

CommanderGenius is actually designed from the start to rebuild
existing SDL 1.2 / 2.0 / OpenGL projects as Android applications, and
includes dozens of examples to work with. So in mid-May this year I
set about splicing together Daniel Kochmański's ECL-ANDROID Java
wrapper and startup code (which together load ECL as a shared object
from within the app) into the CommanderGenius SDL application code and
build procedures.

The result is a fullscreen SDL/OpenGL application with Embeddable
Common Lisp, optionally running Swank. There's even a configurable
splash screen!

3.3.2 Do a little dance with ASDF

ECL can compile an entire system into one FASL file, but I ran into a
snag with the ASDF-based build procedure. The typical way is to
compile each Lisp file and then load the resulting compiled file. But
on the cross-compiler,

fails because the output of COMPILE-FILE is a binary for the wrong
architecture. Likewise, alien shared libraries cannot be loaded during
Lisp compilation, which broke CL-OPENGL and LISPBUILDER-SDL.

My temporary solution was to redefine the function
ASDF:PERFORM-LISP-LOAD-FASL in my build script. My modified version
does something like this instead:

I then invoke ECL's system builder, which spits out a big binary FASB
file containing the whole system. But thanks to the LOAD statements,
each Lisp file has had access to the macros and other definitions that
preceded it in compilation.

I'm sure this is really wrong, but it works, and the resulting FASBs
load very quickly. (App startup time went from over 30 seconds when
loading byte-compiled FASCs, to about 3.5 seconds.)

In the end, it was simple to deal with CL-OPENGL and LISPBUILDER-SDL
wanting to open shared libraries during compilation. I used Grep to
find and then comment out calls to CFFI:USE-FOREIGN-LIBRARY, leaving
the DEFINE-FOREIGN-LIBRARY definitions intact. This allows
cross-compilation to proceed normally.

Then on Android, after the FASBs are loaded I invoke
USE-FOREIGN-LIBRARY on each of the required definitions.

So tricking ASDF works. But aside from being a hack, it's not enough
for some of the things I'd like to do. The INLINED-GENERIC-FUNCTION
technique looks like a highly promising way to increase performance,
but my cross-compilation trick led in this case to invalid FASB's with
embedded FASC bytecodes. Indeed, to work with ECL in this situation
would require actually loading the ARM-architecture compiled
INLINED-GENERIC-FUNCTION binary before compiling systems that use
inlining—which as mentioned above cannot be done during
cross-compilation.

I'm exploring other potential solutions, such as installing a
GNU/Linux container on my Android development unit in order to give
ECL access to a native C compiler toolchain (see below). I may even
attempt to write a custom cross-compilation procedure using Clang and
LLVM. But this is less urgent for now, because tweaking ASDF is
sufficient to produce a working application.

3.3.3 Use OpenGL ESv1 with CL-OPENGL

Luckily the the path of least resistance could prevail here. OpenGL ES
version 1 is widely supported on Android devices, and is easier to
port to from Immediate mode than is GLESv2. CL-OPENGL supports it
right out of the box. (I'd like to thank 3-B and oGMo for their help
in bridging the gap with my own code.)

Some tasks remain to be done here but most of Xelf's drawing functions
are now working, including TrueType fonts and vertex coloring.

I've also written some code to partially emulate vertex coloring as a
way of increasing render performance, and this will be covered in the
forthcoming Part 2 of this article.

3.3.4 ProTip: Use the byte-compiler

One issue has gone unmentioned. How do I interactively redefine
functions and set variables in order to develop the running game via
SLIME/Swank, if everything must be cross-compiled on an X86 system?

The answer is that ECL's built-in bytecode compiler is used in these
cases, and the bytecoded definitions replace the originals. I can
freely use COMPILE-FILE, LOAD, and even ASDF:LOAD-SYSTEM during "live"
development; under normal circumstances the only real difference is
execution speed of the resulting code. The final game app will ship
without Swank, of course, and with a fully native Lisp stack.

Now you have a new problem, which is how to edit the Lisp files on
your Android device so that Swank can compile and load them.

3.3.5 ProTip: Use Emacs TRAMP with ADB

To make this useful you need a rooted android device.

This can integrate with Emacs' "bookmarks" and "desktop" features for
even more convenience.

3.3.6 ProTip: Use Emacs to inspect your APK package

They're just zip files. Missing libraries or assets? Check the APK by
opening it as a file in GNU Emacs.

3.3.7 ProTip: Use a GNU/Linux container for SSH and native Emacs with X11!

You can actually install a GNU/Linux "container" with Debian, Ubuntu,
or some other distribution on your Android development system in order
run the Secure Shell daemon and many other applications. I use it to
run a graphical Emacs on the Android box, with Emacs' X11 connection
forwarded through SSH so that its windows open on my desktop GNU/Linux
PC's X server—right alongside my native Emacs. I use different color
themes to avoid mixing them up.

This gives me full access to everything on both systems from a single
mouse/keyboard/monitor, and I can cut and paste text freely between
applications.

Setting up such a container is beyond the scope of this article, but I
highly recommend it. It was pretty easy on a rooted device, and works
very well.

3.4 Conclusion

In less than a month we went from "let's do it" to "wow, it works!"
What more can you ask for?

This concludes Part 1 of my article on building Lisp games for Android
with Embeddable Common Lisp. To read my running commentary and see
news and test results as they are posted, you can visit the project
README:

https://gitlab.com/dto/ecl-android-games-src/blob/master/README.org

More details and all scripts and configurations can be found in that
repository.

Thanks for reading,



David O'Toole (dto@xelf.me)

11 June, 2016

4 Common Lisp implementations

Some time ago I've created with the help of many kind people (most
notably from Rainer Joswig and Fare Rideau) a graph presenting Common
Lisp implementations and the relations between them. This version is
improved over drafts presented on twitter and linkedin. If you
find any errors, please contact me.



It is worth noting that LispWorks and VAX share the code with
Spice Lisp which later evolved into Common Lisp
implementation CMUCL. Striped lines lead to CMUCL, because I
didn't want to add pre-CL implementations.

There is also suspicion that Lucid shares code with Spice Lisp
and/or VAX, but I couldn't confirm that, so I'm leaving it as is.

"JavaScript Lisp Implementations" classifies some lisps as CL, but
I've added only Acheron and parenscript to the list, because rest
is just CL-ish, not even being a subset.

Resources I've found on the internet: CMU FAQ, ALU list, CLiki
overview, Wikipedia article, JavaScript Lisp Implementations.

5 Building various implementations

I've built various lisps to perform some benchmarks and to have some
material for comparison. Ultimately I've decided to polish it a little
and publish. I had some problems with Clasp and Mezzano so I've
decided to not include them and leave building these as an exercise
for the reader ;-). Also, if you feel adventurous, you may try to
build Poplog, which has Common Lisp as one of the supported languages.

If you want to read about various implementations, please consult
Daniel's Weinreb Common Lisp Implementations: A Survey (material from
2010, definitely worth reading).

First we create a directory for the lisp implementations (we'll build
as an ordinary user) and download the sources. Each implementation has
a list of building prerequisites, but it may be not comprehensive.

5.0.1 ABCL (Armed Bear Common Lisp)

Requires

jdk, ant

5.0.2 CCL (Clozure Common Lisp)

Requires

gcc, m4, gnumake

5.0.3 CLISP

Requires

gcc, make

Notes

don't build with ASDF (it's old and broken)

5.0.4 CMUCL (CMU Common Lisp)

Requires

cmucl binary, gcc, make, openmotif

Notes

it needs another CMUCL to bootstrap (release 21a)

5.0.5 ECL (Embeddable Common Lisp)

Requires

gcc, make

5.0.6 JSCL (Java Script Common Lisp)

Requires

Conforming CL implementation, web browser, nodejs

Notes

Doesn't provide LOAD yet (no filesystem), but author
confirmed that this will be implemented (virtual filesystem on
the browser and the physical one on the nodejs).

5.0.7 GCL (GNU Common Lisp)

Requires

gcc, make

5.0.8 MKCL (Man-Kai Common Lisp)

Requires

gcc, make

5.0.9 SBCL (Steel Bank Common Lisp)

Requires

ANSI-compliant CL implementation

Notes

Lisp has to close on EOF in top-level (CMUCL doesn't do that),

ECL has some bug regarding Lisp-to-C compiler apparently triggered
by the SBCL compilation - don't use it here,

we could use precompiled SBCL like with the CMUCL, but let's
exploit the fact, that we can compile from the C-bootstrapped
implementation (we'll use already built clisp-dev),

it is advised to run the script in fast terminal (like xterm) or
in the terminal multiplexer and to detach it - SBCL compilation
process is very verbose,

if you build SBCL on Windows, consider using MinGW to preserve
POSIX compatibility.

5.0.10 WCL

Requires

tcsh, gcc, git

Notes

very incomplete implementation

5.0.11 XCL

Requires

gcc

Notes

last commit in 2011

6 Portability libraries

It is important to know the difference between the language standard,
implementation-specific extensions and the portability libraries. The
language standard is something you can depend on in any conforming
implementation.

Sometimes it's just not enough. You may want to do ** serializethreading*, or to
*data, which is very hard to express (or even impossible)
in the language provided by the standard. That's where the
implementation-specific extensions kick in. Why are they called
"implementation-specific"? Because the API may be different between
implementations - reaching consensus is a hard thing1.

The most straightforward approach I can imagine is to reach for the
documentation of the Common Lisp implementation you are currently
using and to use the API provided by this implementation. I dare you
not to do that! It's definitely the easiest thing to do at first, but
mind the consequences. You lock yourself, and your users in the
implementation you prefer. What if you want to run it on the JVM or
to make it a shared library? Nope, you're locked-in.

"What can I do then?" - you may ask. Before I answer this question,
I'll tell you how many people do it (or did it in the past) - they
used read-time conditionals directly in the code. Something like the
following:

If the creator felt more fancy and had some extra time, they put it in
the package my-app-compat. It's all great, now your application
works on all supported implementations. If somebody wants theirs
implementation to work, send the creator a patch, who incorporates it
into the code and voila, everything works as desired.

We have one problem however. Libraries tend to depend on one
another. There is also a lot of software which uses features beyond
the ANSI specification (it's all good, programmers need these!). Do
you see code duplication everywhere? How many times does a snippet
above have to be copy-pasted, or rewritten from scratch? It's not
black magic after all. APIs between ad-hoc implementations don't
exactly match, covered CL implementations differ…

So you quickload your favorite library which depends on 10 other
libraries which implement BAZ functionality in theirs own unique
way, with a slightly different API on the unsupported implementation -
that's why we have my-baz abstraction after all, right? Now, to make
it work, a user has to:

Find which of the ten libraries don't work (not trivial!),

find and clone the repositories (we want to use git for patches),

fix each one of them (grep helps!) and commit the changes,

push the changes to your own forked repository and create a pull
request (or send a diff to the mailing list) - *ten times*,

voila, you're done, profit, get rich, grab a beer.

It's a lot of work which the user probably won't bothered to do. They
will just drop the task, choose another implementation or hack their
own code creating the Yet Another Baz Library for the
implementations he cares for reinventing the wheel once more. It's a
hacker's mortal sin.

I'm going to tell you now what is the Right Thing™ here. Of course you
are free to disagree. When you feel that there is a functionality you
need which isn't covered by the standard you should

Look if there is a library which provides it.

You may ask on IRC, the project's mailing list, check out the
CLiki, do some research on the web. Names sometimes start with
trivial-*, but it's not a rule. In other words: do your homework.

If you can't find such a library, create one.

And by creating such a library I mean comparing the API proposed by
at least two CL implementations (three would be optimal IMHO),
carefully designing your own API which covers the functionality (if
it's trivial, this should be easy) and implementing it in your
library.

Preferably (if possible) add a fallback implementation for
implementations not covered (with the appropriate warning, that it
may be inefficient or not complete in one way or another).

It may be worth reading the Maintaining Portable Lisp Programs
paper written by Christophe Rhodes.

Write beautiful documentation.

A CL implementation docs may be very rough. It takes time to write
them and programmers tend to prioritize code over the
documentation. It's really bad, but it's very common for the
documentation to be incomplete or outdated.

Document your library, describe what it does, how to use it. Don't
be afraid of the greatness! People will praise you, success will
come, world will be a better place. And most importantly, your
library will be useful to others.

Publish the library.

Make that library your project's dependency.

I know it's not easy, but in the long term it's beneficial. I
guarantee you that. That's how the ecosystem grows. Less duplication,
more cooperation - pure benefit.

Some people don't follow this path. They didn't think it through, or
maybe they did and decided that keeping the dependency list minimal is
essential to their project, or were simply lazy and hacked their own
solution. There are also some old projects which exported a number of
features being a very big portability library and an application at
the same time (ACL-compat, McCLIM and others). What to do then?

If it's a conscious decision of the developer (who doesn't want to
depend on /anything/), you can do nothing but provide a patch adding
your own implementation to the supported list. It's their project,
their choice, we have to respect that.

But before doing that you may simply ask if they have something
against plugging these hacks with the proper portability library. If
they don't - do it, everybody will benefit.

There are a few additional benefits of the presented portability
library approach for the implementations itself. Having these internal
details in one place makes it more probable that your implementation
is already supported. If the library has a bug it's easier to fix it
in one place. Also, if the CL implementation changes it's API, it's
easy to propagate changes to the corresponding portability
libraries. New CL implementation creators have a simplified task of
making their work usable with existing libraries.

It is worth noting, that creating such library paves the way to the
new quasi-standard functionalities. For instance Bordeaux Threads has
added recently CONDITION-WAIT function, which isn't implemented on
all implementations. It is a very good stimulus to add it. This is how
library creators may have real impact on the implementation creators
decisions about what to implement next.

6.1 Portability layer highlights

Here are some great projects helping CL implementations be part of a
more usable ecosystem. Many of these are considered being part of the
de-facto standard:

bordeaux-threads

Provides thread primitives, locks and conditionals

cl-store

Serializing and deserializing CL objects from streams

cffi

Foreign function interface (accessing foreign libraries)

closer-mop

Meta-object protocol - provides it's own
closer-common-lisp-user package (redefines for instance
defmethod)

usocket

TCP/IP and UDP/IP socket interface.

osicat

Osicat is a lightweight operating system interface for Common
Lisp on POSIX-like systems, including Windows

cl-fad

Portable pathname library

trivial-garbage

trivial-garbage provides a portable API to finalizers, weak
hash-tables and weak pointers

trivial-features

trivial-features ensures consistent *FEATURES* across multiple
Common Lisp implementations

trivial-gray-streams

trivial-gray-streams system provides an extremely thin
compatibility layer for gray streams

external-program

external-program enables running programs outside the Lisp
process

There are many other very good libraries which span multiple
implementations. Some of them have some drawbacks though.

For instance IOlib is a great library, but piggy-backs heavily on UN*X
- if you develop for many platforms you may want to consider other
alternatives..

UIOP is also a very nice set of utilities, but isn't documented well,
does too many things at once and tries to deprecate other actively
maintained projects - that is counterproductive and socially
wrong. I'd discourage using it.

There are a few arguments supporting UIOP's state - it is a direct
dependency of ASDF, so it can't (or doesn't want to) depend on other
libraries, but many utilities are needed by this commonly used system
definition library. My reasoning here is as follows: UIOP goes
beyond ASDF's requirements and tries to make actively maintained
projects obsolete. Additionally it works only on supported
implementations even for features which may be implemented portably.

6.2 UIOP discussion

I'm aware that my opinion regarding UIOP may be a bit
controversial. I've asked the library author and a few other people
for feedback which I'm very grateful for. I'm publishing it here to
keep opinions balanced.

6.2.1 Fare Rideau

Dear Daniel,

while there is a variety of valid opinions based on different
interests and preferences, I believe your judgment of UIOP is based on
incorrect premises.

First, I object to calling UIOP "not well documented". While UIOP
isn't the best documented project around, all its exported functions
and variables have pretty decent DOCSTRINGs, and there is at least one
automatic document extractor, HEΛP, that can deal with the fact that
UIOP is made of many packages, and extract the docstrings into a set
of web pages, with a public heλp site listed in the UIOP
README.md. The fact that some popular docstring extractors such as
quickdocs can't deal with the many packages that UIOP creates with its
own uiop:define-package doesn't mean that UIOP is less documented than
other projects on which these extractors work well, it's a bug in
these extractors.

Second, regarding the deprecation of other projects: yes, UIOP does
try to deprecate other projects, but (a) it's a good thing, and (b) I
don't know that any of the projects being deprecated is "actively
maintained". It's a good thing to try to deprecate other lesser
libraries, as I've argued in my article Consolidating Common Lisp
libraries: whoever writes any library should work hard so it will
deprecate all its rivals, or so that a better library will deprecate
his and all rivals (such as optima deprecating my
fare-matcher). That's what being serious about a library is all
about. As for the quality of the libraries I'm deprecating, one
widely-used project the functionality of which is completely covered
by UIOP is cl-fad. cl-fad was a great improvement in its day, but some
of its API is plain broken (e.g. the :directories argument to its
walk-directory function has values with bogus names, while its many
pathname manipulation functions get things subtly wrong in corner
cases), and its implementation not quite as portable as UIOP (that
works on all known actively used implementations). There is no reason
whatsoever to ever choose cl-fad over UIOP for a new project. Another
project is trivial-backtrace. I reproduced most of its functionality,
except in a more stable, more portable way (to every single CL
implementation). The only interface I didn't reproduce from it is
map-backtrace, which is actually not portable in trivial-backtrace
(only for SBCL and CCL), whereas serious portable backtrace users will
want to use SLIME's or SLY's API, anyway. As for external-program, a
good thing it has for it is some support for asynchronous execution of
subprocesses; but it fails to abstract much over the discrepancies
between implementations and operating systems, and is much less
portable than uiop:run-program (as for trivial-shell, it just doesn't
compete).

UIOP is also ubiquitous in a way that other libraries aren't: all
implementations will let you (require "asdf") out of the box at
which point you have UIOP available (exception: mostly dead
implementations like Corman Lisp, GCL, Genera, SCL, XCL, may require
you to install ASDF 3 on top of their code; still they are all
supported by UIOP, whereas most portability libraries don't even
bother with any of them). This ubiquity is important when writing
scripts. Indeed, all the functionality in UIOP is so basic that ASDF
needed it at some point — there is nothing in UIOP that wasn't itself
required by some of ASDF's functionality, contrary to your claim that
"UIOP goes beyond ASDF's requirements" (exception: I added one
function or two to match the functionality in cl-fad, such as
delete-directory-tree which BTW has an important safeguard argument
:validate; but even those functions are used if not by ASDF itself, at
least by the scripts used to release ASDF itself). I never decided
"hey, let's make a better portability library, for the heck of
it". Instead, I started making ASDF portable and robust, and at some
point the portability code became a large chunk of ASDF and I made it
into its own library, and because ASDF is targetting 16 different
implementations and has to actually work on them, this library soon
became much more portable, much more complete and much more robust
than any other portability library, and I worked hard to achieve
feature parity with all the libraries I was thereby deprecating.

Finally, a lot of the functionality that UIOP offers is just not
offered by any other library, much less with any pretense of universal
portability.

6.2.2 David Gu

For the documentation thing, I really think Quickdocs could do a
better job. The bug #24 stated that problem, however, it's remain to
be solved. I will check this out if I have free time recently.

I use UIOP a lot in my previous company, the reason is simple and
maybe a little naive: my manager didn't want to involve too many
add-ons in the software. UIOP is shipped together with ASDF, it's
really "convenient", and its robustness is the final reason why I will
stick to it. If people understand how UIOP came out in the history
from ASDF2 to ASDF3, I think people will understand why it's acting
like deprecating several other projects – that's not the original
idea of it.

But anyway, I really learned a lot from this post and also the
comments. In my opinion, avoid reinventing the wheels is the right
idea and directions for this community. So from that perspective, I
support @fare's idea "It's a good thing to try to deprecate other
lesser libraries". Including this article and along with Maintaining
Portable Lisp Programs and @fare's Consolidating Common Lisp
Libraries, we should let more people involved in this topic.

Footnotes:

1

If you are Common Lisp implementer and plan to add a feature
beyond ANSI specification, please consider writing a proposal and
submitting it to Common Lisp Document Repository. It will make
everybody's life easier.

Show more