Announcing uLisp Release 4.6 for all versions of uLisp


Here’s a summary of the new and updated features for the AVR, ARM, ESP, and RISC-V versions of uLisp in Release 4.6:

  • A *features* variable that returns a list of keywords representing the capabilities of the version of uLisp.

    For example:

    > *features*
    (:floating-point :arrays :documentation :machine-code :error-handling :wi-fi :gfx)

    For example, to check if your version has floating point you can do:

    (member :floating-point *features*)
  • A copy-list function that returns a copy of a list.

  • In addition to the dolist and dotimes iteration constructs, uLisp 4.6 now includes the more flexible do and do* that allow an unlimited number of loop variables, each with an optional initial value and optional step-form, and an end test.

  • uLisp 4.6 now provides three additional map functions: mapcon, mapl, and maplist. These complete the matrix of six map functions in Common Lisp, for flexibility with the way you can map a function over one or more lists of elements. See Processing items in a list.

  • uLisp 4.6 now includes three additional string comparison functions: string/=, string<=, and string>=.

  • A new :test keyword parameter allows you to specify an alternative test function for assoc, member, and search. For example you can do:

    > (assoc "three" '(("one" . "eins") ("two" . "zwei") ("three" . "drei")) :test #'string=)
    ("three" . "drei")
  • You can now use setf to modify a character in a string. For example:

    > (let ((s "abc")) (setf (char s 1) #\r) s)
  • User-defined keywords are now recognised as keywords that evaluate to themselves,:

    > :fred
  • A number of minor bug fixes and improvements have been incorporated; thanks to @dragoncoder047 for many of these.

All of these improvements have been incorporated without having an impact of the performance of uLisp, or the amount of workspace available on each platform.

The AVR-Nano version of uLisp has also been updated to incorporate the bug fixes, but it was not possible to fit the new features in the 32Kbytes available on the platforms it supports.

Download Release 4.6 for your platform from the Download uLisp page.


These are awesome additions. I feel the language just got more powerful. :D


Hi David ,

Thanks for ulisp 4.6 !
Works nice on my rpi pico with sdcard support.
And thanks for mentioning my “brave work” on the serial ports on the grand central M4 ;-)



Thanks a lot for the new release! I’m currently looking into it to merge it with my forks - one question concerning the ARM version: What was your reason for not using PROGMEM anymore, esp. concerning the LispLibrary?


PROGMEM doesn’t have any effect on ARM processors, and it was previously just ignored by the compiler, so I decided it was tidier to remove it.


Thank you for the clarification!


Sorry to bother you again, but I’m having serious trouble with 4.6 merged into my (not yet public) LispBox fork. My merged version seems to run fine handling a quite complex Lisp program and then crashes at reproducible points entirely without any error message. I cannot figure out why.
It might have to do something with using “return” in a “case” block within a “loop” context. (Not sure if this is legal at all…) Thus, it might help if I understand why and in what way the implementation of “return” changed from this…

object *sp_return (object *args, object *env) {
object *result = eval(tf_progn(args,env), env);
return result;

… to the new version:

object *fn_return (object *args, object *env) {
(void) env;
if (args == NULL) return nil; else return first(args);

Again, this is a reproducible crash, but without error messages. I tried really hard to track down the culprit in my uLisp program and the slightly modified .ino file, but without luck. I’ll probably have to redo the merge process because it is entirely possible I overlooked something and did it wrong, but inspecting the differences again and again have not revealed any clue yet what might have gone wrong.
Thank you for your help!


The reason I changed sp_return() to fn_return() is because there’s no need for it to be a special form; it can be a regular function. It shouldn’t affect your program.

It might have to do something with using “return” in a “case” block within a “loop” context.

That’s certainly legal. Does your Lisp program run OK on the standard uLisp release 4.6? If not, it may be a bug that I’d like to track down.

You’re welcome to email me your uLisp fork, and/or the program causing the crash with details of where it crashes, and I’ll take a look.


Thanks a lot for your offer. I’ll try a clean merge once again and see what happens. If the problem persists, I’ll get back to you with the whole thing. Thanks again!

Solved. This was not related to the migration to 4.6, but rather to this problem:

… again. So be aware: uLisp extension functions must return a uLisp object* by all means, at least nil or tee, even if the function in itself is not meant to return any value at all. For some reason the compiler does not complain when a C function of type object* omits an explicit “return” statement. It was pure luck the tiny function in question somehow worked with 4.5 without crashing it.


Thanks - I’ll add a note to that effect on the Extensions page.


2 posts were split to a new topic: Lisp Badge LE firmware updated to uLisp 4.6