💾 Archived View for thrig.me › blog › 2022 › 11 › 10 › common-lisp-problems.gmi captured on 2024-07-09 at 00:54:13. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-12-28)

-=-=-=-=-=-=-

Common LISP Problems

The below is probably better said in

https://mfiano.net/posts/2022-09-04-from-common-lisp-to-julia/

Indentation

One is expected to use emacs, and let it do whatever it does by way of indentation. If you show code not in emacs style, you'll probably get yelled at, a point mfiano also touches on. A request for a tool that accepts LISP on standard input and emits properly formatted code on the output met with silence. And the default style looks like one of those print jobs where the carriage return never happen and the text helpfully stairsteps right off the page. I lean towards the low end of the optimal line length range, and almost never set my terminals wider than 80 columns.

    (defun main ()
      (let ((app (new-game)))
        (sdl2:with-init (:everything)
                        (sdl2:with-window (win :title "Test" :w 640 :h 640 :flags '(:shown))
                                          (sdl2:with-renderer (renderer win :flags '(:accelerated))
                                                              (event-loop app))))))

This is nigh unreadable in vi; if I were to use a wider terminal I would have trouble scanning to the next line, and anyways that would not excuse all that wasted space where the text mostly should be, up against the left margin. Are there knobs to fix this problem? Have not found them, yet.

Perl has better indentation support than Common LISP via Perl::Tidy--not perfect, there are problems, notably with attributes found in Object::Pad--but perltidy does not require frequent manual fiddling to avoid macro stairsteps. clang-format does a very good job on C. Go has only one way to format the code. Years later I did find cl-indentify which does a much better job than something I had rigged up to mangle lisp, but cl-indentify still does the macro stairstep thing. Hence Perl having better indentation support; there is much less to manually fiddle with. Common LISP is better on the automatic indentation front than, say, TCL, or FORTH, but it's not anywhere near the awards podium, either.

Why Use a Tool to Indent?

For one, I do not use a fancy IDE, so it's up to what vi can do, therefore mostly what filters provide. Another reason is that a programmer at Apple wrote gotofail wherein misleading indentation lead to CVE-2014-1266. There are other ways this security vulnerability could have been avoided--test coverage, code reviews, and compiler warnings come to mind--but I send all my C code through clang-format (formerly, GNU indent) to help surface indentation problems.

One might also want to keep the NSA out of the standards process so that the protocol does not become needlessly bloated and therefore CVE prone. If wishes were horses...

Fancy IDE

They are slow to get up off disk, tend to peg multiple CPU cores doing nothing, often beachball the cursor because everyone loves lag, generally are not available on OpenBSD, typically render code with colors most unreadable, and can kill the development environment by making 50 connections to the test database which caused me to be yelled at because my username "jmates" looked very similar to that of the intern "jmate" who was running the Eclipse that had just snafu'd all of dev.

Not really what I look for as a hobbyist programmer, in other words.

Libraries

Eventually Common LISP got Quicklisp (which has problems) and it does have ASDF, which can probably do everything (but not download things from the Internet for you) while also being bear to learn; I've only nibbled around the edges of the ASDF manual. The Quicklisp blog only goes back to 2010; CPAN for Perl by contrast dates to 1993. Typically LISP is decades ahead of other languages, but not in this department.

The libraries are pretty spotty (similar complaints can be made about CPAN, or equivalent) especially on OpenBSD, where things like SDL2-TTF do not compile.

    $ quicklisp install sdl2-ttf
    To load "sdl2-ttf":
      Load 1 ASDF system:
        sdl2-ttf
    ; Loading "sdl2-ttf"
    ...................Unhandled CFFI:LOAD-FOREIGN-LIBRARY-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
                                                           {1001E10073}>:
      Unable to load any of the alternatives:
       ("libSDL2_ttf-2.0.so.0" "libSDL2_ttf")

    Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {1001E10073}>
    ...
    $ pkglocate libSDL2_ttf
    sdl2-ttf-2.0.15p0:devel/sdl2-ttf:/usr/local/lib/libSDL2_ttf.a
    sdl2-ttf-2.0.15p0:devel/sdl2-ttf:/usr/local/lib/libSDL2_ttf.la
    sdl2-ttf-2.0.15p0:devel/sdl2-ttf:/usr/local/lib/libSDL2_ttf.so.0.0
    $ pkg-config --cflags --libs SDL2_ttf
    -I/usr/local/include/SDL2 -I/usr/X11R6/include -D_REENTRANT -L/usr/local/lib -L/usr/X11R6/lib -lSDL2_ttf -lSDL2

Maybe you find a library that meets your need, maybe you don't, maybe you have the tuits to fix the libraries that do not work, maybe you don't. The compiles are generally quick, so on the plus side it's usually not too long to wait for something to either blow up or install.

Documentation

Common LISP does not really have a standard for documentation, so libraries vary between "read the code, lol!" (this is not unique to Common LISP) to having some giant TeX blob that fails to compile, or maybe there's HTML, or who knows what. Thankfully none of it (so far) has mandated JavaScript. By contrast, perldoc Module::Name is very likely to get you what you want, and library bootstrap utilities (Module::Starter, etc) create POD coverage test scripts by default. This might also be a cultural thing, where in Perl it's the culture to ship things with a goodly amount of POD.

    $ cd alexandria-20220707-git/doc
    $ make
    sbcl --no-userinit --eval '(require :asdf)'  --eval '(let ((asdf:*central-registry* (list "../"))) (require :alexandria))'  --eval '(with-compilation-unit () (load "docstrings.lisp"))'  --eval '(sb-texinfo:generate-includes "include/" (list :alexandria-1 :alexandria-2) :base-package :alexandria)'  --eval '(quit)'
    This is SBCL 2.2.5.openbsd, an implementation of ANSI Common Lisp.
    More information about SBCL is available at <http://www.sbcl.org/>.

    SBCL is free software, provided as is, with absolutely no warranty.
    It is mostly in the public domain; some portions are provided under
    BSD-style licenses.  See the CREDITS and COPYING files in the
    distribution for more information.
    texi2pdf alexandria.texinfo
    This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2021-OpenBSD_Ports) (preloaded format=pdfetex)
     restricted \write18 enabled.
    entering extended mode
    (./txiversion.tex
    ! I can't find file `texinfo.tex'.
    l.1 \input texinfo.tex
                           @bye
    (Press Enter to retry, or Control-D to exit)
    Please type another input file name:
    ! Emergency stop.
    l.1 \input texinfo.tex
                           @bye
    !  ==> Fatal error occurred, no output PDF file produced!
    Transcript written on txiversion.log.
    /usr/bin/texi2dvi: texinfo.tex appears to be broken, quitting.

Hoof! No tuits to debug that. Luckily Alexandria did have a PDF available somewhere; users will follow the path of least resistance. But having to hunt around for documentation that may not exist is maybe not the funnest thing in the world. A standard won't make everyone happy, but a minimum bar that is customary and consistent is probably better than "good luck, it's a jungle out there".

Docstrings are a standard, but these will be variously unused, or have short little hints in them (this is probably their Goldilocks zone), or sometimes a few paragraphs. Meanwhile, someone at Microsoft figured out--back in the 80s, but I cannot find the paper now--that documentation should exist in multiple forms: tutorials, cookbooks, technical reference, other (literate programming, angry blog rants, other). Docstrings do not really fit anything from that list; maybe for very simple things the technical documentation might all fit into a docstring, but then you still lack a standard means to provide documentation such as

    $ search | fgrep /Mojo | fgrep .pod
    ./MojoX/MIME/Types.pod
    ./Mojolicious/Guides/Growing.pod
    ./Mojolicious/Guides/Contributing.pod
    ./Mojolicious/Guides/Cookbook.pod
    ./Mojolicious/Guides/FAQ.pod
    ./Mojolicious/Guides/Rendering.pod
    ./Mojolicious/Guides/Routing.pod
    ./Mojolicious/Guides/Testing.pod
    ./Mojolicious/Guides/Tutorial.pod
    ./Mojolicious/Guides.pod

There are a bundle of good books for Common LISP, Practical Common LISP in particular. The language tends not to change randomly (I consider this a good thing) which means the books have not bitrotted much or at all.

Tests

Again there is no standard, nor does there appear to be any sort of smoketest system like CPAN has (TAP is probably terrible, but terrible could be better than "it's a jungle out there"). Luckily folks have put together pages like

https://sabracrolleton.github.io/testing-framework

and eventually I settled on fiveam. Probably need to find something that provides code coverage (./Build testcover for my perl modules) but that's more work. A hobbyist programmer might instead look for a language where something good enough is already setup and there.

Conclusion

Given that I mostly write scripts for unix (C, Perl) and do not use live coding (nor emacs) Common LISP probably isn't actually a good fit. But it is educational to learn about macros, and LISP is a fairly fast language to prototype in (yes, even in vi) that can compile pretty quick code pretty quickly. And is actually available on OpenBSD, even if I probably do need to roll up my sleeves and figure out why some of those modules fail to compile (or do without SDL2 TTF).

And hey I like using old dead languages.

tags #lisp #perl