Newbie, comparison to MicroPython


#1

Hi All,

Moderately experienced non-dev, have started to dip my toes into Common Lisp. Since my main motivation is uControllers, can anyone give a comparison in speed/size vs something like Micropython?
Honestly though, CL is so orthogonal to my previous experience, I’m hoping uLisp might be a little easier to ease into.
Appreciate any comments, thanks.


#2

Not based on measurements but on feeling/usage uLisp probably is somewhat less speedy than MicroPython, but that may depend on your code/use case. That said there’s the option to outsource critical parts to the (currently limited) uLisp compiler, Assembler or extensions written in C.
When I started using uLisp I wasn’t quite sure if I should take on the challenge to really (re-)learn Lisp up to a productive stage, but for me it was 1) well worth the effort and 2) not that much an effort at all, mostly because David offers complete and concise documentation with tons of well explained examples. So I’d say take the plunge, it’s not only fun, but indeed less intimidating than CommonLisp because of the carefully selected subset of language elements. I didn’t regret trying it out and even made uLisp my main MCU development platform. One reason is I consider uLisp as really “open” in the best sense, so I don’t feel tied to a huge black box maintained by a quite large community of developers, but rather have been able to understand the language core myself to a useful extent, step by step. Plus, David and everyone else here offers help really quick.


#3

uLisp has a much smaller and simpler implementation and can run on much smaller hardware. The big selling point for me as a C programmer is that it’s easy to modify it internally, add features and drivers, and port it to other devices. That said, the user experience of using it as a beginner can be rough. There isn’t much documentation on how to use lisp in general for writing modern software, and even less for using uLisp and writing embedded software. The uLisp site’s documentation is fantastic for understanding the basics and even covers how it works internally, but knowing how to use lisp well is it’s own skill. I suspect that many people who come to uLisp are experienced lisp users.

The tooling is also tricky. Compiling and uploading uLisp is great because it’s just Arduino. But stuff like code formatting and editing greatly benefits from editors that understand lisp code (parentheses balancing, indentation).

Also uLisp doesn’t really have libraries or separate files for different code like micropython does. Iirc the experience is smoother for micropython (I used circuitpython when I tried it actually) because it presents itself as a flash drive and you can just edit the code in the file in the drive. Also you can download libraries and other peoples code files and put them on the device. There’s also likely more code and drivers already written for you.

That said I never found micropython compelling because if one’s goal is having a lot of libraries and prewritten code then regular Arduino is a much better alternative; it runs faster, is better supported, has tons of code and tutorials, is easy to understand, and is ported to so many platforms. Micropython is “more dynamic” but I rarely found that to be an advantage in embedded programming and actually enjoy having type checking. With uLisp I get the experience of something really different and novel and that’s the big selling point for me.


#4

I’d like to add I’m still not a really seasoned Lisp programmer (and wasn’t one when I encountered Lisp the first time in my life). That probably shows in my code one way or the other, but nonetheless: The code works well, and I enjoy learning more and more things I can do with this modeling-clay-like language. I agree to @hasn0life that Micro/CircuitPython offer way more libraries to just toss in, but seen from another perspective they really don’t since you can add just any Arduino C library to uLisp with very little effort.

The Pythons are much more (absolute)beginner friendly, but the price for this is something I see as a limitation: Unless you are willing to dive into the really complicated (IMHO) process of extending MicroPython yourself you are stuck with the libraries that already exist - quite a lot, but still less than those in Arduino/C. I can give an example that annoyed me personally: The CircuitPython library for the RFM69 radio modules does not match the communication parameters in the respective Arduino libraries, and programming those modules from scratch is really hard - in the source code of the existing libraries one can see how just about anyone struggles with how to interpret certain parts of the protocol. So I’d need to either use Python only on every board I want to talk to - or use C only, but then I’m thrown back to the old method of coding, compiling, writing, trying with lots of Serial.println, which for me really slows down the process.

When I want to try out ideas and concepts a REPL is godsend, at least for me. With uLisp I feel I can glue the best parts together: Choose the Arduino library I want to and just about any board in my drawer, older ones as well (I still have a couple of 1284P boards I really don’t want to throw away), write a rather small C-to-uLisp wrapper for functions I need from the external library, and then start to interactively develop the “real” code that does something for me. I’m getting faster and faster with the latter without being tied to the Python ecosystem that tends to break older code from time to time by re-organizing libraries and functions. (Don’t get me wrong, I still really like Python as well, but.)

Oops, wrote more than I wanted to. Sorry…


#5

Appreciate the comments.

So far, the hardest thing I’ve found with CL is breaking away from the Imperative/Procedural experience I’ve used most of my life.

Lisp is often called a multi-paradigm language, with the implication that one coming from such will be able to do similar in Lisp.
So far, that seems to be less true than stated.

I will have to peruse the docs and see for myself I guess.
However would you say uLisp is easier to get up to speed with than full Common Lisp?


#6

Lisp is indeed paradigm agnostic and you can mix and match the paradigms you need. For a quick overview of functional programming, which is common in Lisp (no pun intended), this slide deck with code snippets in Common Lisp may help.


#7

This might be useful too:

Introduction to Lisp for C programmers


#8

I’d say it’s because of the hands-on approach with immediate feedback from your electronic components. Conjure up a task and see how you can get it done with uLisp (consult the examples). I think that’s a less theoretical and more rewarding learning experience. CommonLisp has a huge set of special forms etc., therefore I believe uLisps reduced and very direct approach shows the essence of Lisp ands keeps you motivated.


#10

Thanks everyone, I do appreciate your suggestions and time.

Just curious, any thoughts on ESP32 vs Pico/Pico2 W?
I can use either, however ESP32 w/cam was cheaper last I looked, though I guess with tariffs that might be different.


#11

I’d recommend the pico (though I never used it) because it doesn’t have the USB serial limit issue. ESP32 development is cumbersome if you’re using a terminal.


#12

IIRC that was only relevant to the ESP32 variants that have native USB, and even then it was due to a bug on Espresif’s end, that they’ve known about for a while now. The variants without native USB (most notably the original ESP32) don’t have that problem

That being said, I’d still recommend the Pico, especially if you want to do some low-level assembly programming and/or use the uLisp compiler for extra speed. The ESP32 processors are designed with a “write XOR execute” design that makes on-the-fly machine code generation impossible, so there is no uLisp assembler for those processors.


#13

The ESP32 processors are designed with a “write XOR execute” design that makes on-the-fly machine code generation impossible

More precisely, it’s a decision taken in the design of the IDF (ESP32 IoT Development Framework):

This is caused by the memory protection of ESP-IDF: it assumes all executable code comes from the project binary, and that an attempt to re-write code or to execute data is someone maliciously trying to break into the system, and as such needs to be stopped.

It looks like the only way around it would be to recompile the ESP-IDF libraries; at this point I thought it wasn’t worth pursuing it.

See my full discussion on the ESP32 forum here:

How can I write machine code into RAM and then execute it?


#14

Excellent.

I think I will get the Pico and give it a shot since I need one anyways.

Thanks!