Jungle Coder

The musings of a third culture coder and missionary kid

Factor: An impressive stack-based language environment

Recently the Factor programming language had a new 0.98 release, after a 4 year hiatus after the 0.97 release. Finding this on lobsters, I decided to take Factor for a spin again, after years of having left it mostly alone to work on PISC. I decided I wanted to try to build a (still slightly buggy) 4-function calculator, as I find that a good way to gauge how easy/hard it is to use a GUI system for small things, and as a way to gauge what Factor is like in general.

The (quite frankly) awesome

Probably by far the most impressive part of Factor that I’ve seen so far: Factor is the second language I’ve come across that I’d comfortably take on a deserted island without an internet connection (the other being Go with it’s godoc server). This is due to the fact that a) 95% of all Factor documentation I’ve seen is accessible from the included Help browser, and b) the Factor debugger/inspector can inspect itself in great detail. This is the cherry atop Factor: You don’t just get a REPL, you also get a really useful set of debugging tools (especially the object inspector), and can dig into any of the state in the system, and using the help tools, once you understand some basics, you stand a decent chance of being able to either correct the state, or diagnose the bug.

This sort of tooling is something that SmallTalk is famous for, but any time I’ve tried SmallTalk, I’ve usually bounced off of it because most SmallTalk implementations end up living in their own world, making it hard to bring some of my favorite programming tools with me, and making it hard to interact with the outside world (footnote 3). Factor, on the other hand, even though it has an image that can updated to keep state around, and has a really good debugger, still integrates well with the outside world.

Really well, in fact. It’s easy to scaffold a vocabulary USE: tools.scaffold "vocabulary-name" scaffold-vocabulary , and then run USE: editors.sublime (or emacs, or vim, or any of about 24 other fairly popular editors), and then run "vocabulary-name" edit and have it open the vocabulary in the editor in question. This allows you to open up any of the Factor source code in the editor of your choice. And when you’re ready to start using/testing the vocabulary, running "vocabulary-name" reload puts you right into compile-fixing mode, where you can fix the bug in question, and then reload the vocabulary. When I was working on a 4-function calculator using the Factor listener and Sublime Text, it was a really tight feedback loop.

The GUI framework has a pretty nifty sorta-FRP like approach to how to handles data binding in controls, allowing you to daisy chain models (data that can be updated over time) via arrows (models with a quotation they apply to a base model when it’s data changes).

Also, Factor has a mostly working dark-mode setup (there are some sections of the inspector that have poor contrast, but the listener is in a good state), if you dislike the default black-on-white color scheme (I found it difficult for some of the late night hacking I was doing). Run the following commands in the listener (assuming Factor 0.98)

USE: tools.scaffold 
scaffold-factor-boot-rc

Then edit the .factor-boot-rc to look like so:

USE: ui.theme.switching 

dark-mode

Then then run run-bootstrap-init save in the listener, and close and re-open the listener. Viola, Factor’s dark mode!

Consequences of (relative) obscurity

That being said, there are still a few rough edges with Factor. For one, even though most things are documented, and those that are not have easily accessible source, Factor itself has almost no Google presence, which means that you have to be comfortable digging though the included help docs a bit longer to sort things out. This played out in a few practical ways when I was working on the 4-function calculator. Until the end of the project, I missed that gadgets (Factor’s equivalent for controls in WinForms) were subclasses of rectangles, which meant that I could set their width and height by storing to the dim(ension) on a gadget:

"Test" <label> { 200 300 } >>dim "example of a 200x300 label" open-window 

I ended up looking around the documentation about 4 times before I made that connection. This is the sort of question that would be on stack overflow for a more popular language.

For another, I seemed to be running across rendering or state glitches in the listener that could cause buttons to be mislabeled. I’m unsure what was leading to it, but it was distracting, to say the least. The other thing with Factor that became evident was the singled threaded nature of it’s runtime (as of currently). When first making a search in the help system, it would lock up, sometimes as long as 10-15 seconds, as it was indexing or loading in the various articles and such into memory. This limitation has kept me from digging into some languages (like Ocaml, though there are a bunch of other reasons, like iffy Windows support) in the past, especially when alternatives like Go and Erlang with their strong multi-threaded runtimes exist, but I think I’m willing to look past it in Factor for now, especially since I hear that there is a half decent IPC story for Factor processes.

The other consequence of all this was that it took me roughly 10-15 hours of noodling around with Factor, and writing an even smaller example GUI script to be able to get the linked calculator above done. I think I could build other new things with far less stumbling around, but it was a good reminder of how slow learning something new can be.

The other minor frustration I have with Factor is the fact that any file that does much work tends to accrete quite a few imports in its USING: line (the calculator I wrote has 23 imports across 4 lines, even though it’s only 100 lines of code). This is mostly due to a lot of various Factor systems being split into quite a few vocabularies. I could see this being helpful with compilation

Comparisons to PISC

Factor was a big inspiration for Position Independent Source Code (PISC), especially since it gave me the idea of code quotations some basic ideas for a few stack shuffling operations and some combinators (like when or bi). Factor and PISC have diverged a decent amount, though Factor is far and away further down the general path I’d been wanting to take PISC in terms of documentation and interactivity. Revisiting it after spending 3 years of assorted free time working with PISC demonstrated that in a lot of ways.

Factor has a much higher level of introspection. When making the calculator I only had to think in Factor, rather than thinking in both PISC and Go (which is common when writing PISC). I also didn’t have to rebuild many building blocks to get where I was going, like I would in PISC, as Slava and the other maintainers have done a lot of the foundational work already. Revisiting Factor after having written so much PISC did make understanding the stack a lot easier. I imagine that stack management will be most people’s struggle with Factor. I’ve found that implementing a stack language helped me there, but for some people, they may just have to do some exercises with it.

Conclusions

I do anticipate building more side-projects in Factor, as I’ve yet to try out the web framework, and I have a couple of ideas for websites in the back of my mind. There’s a lot of vocabularies that come with the base Factor download. I get the feeling that I may be adding some to it in the future, though time will tell.

Previously: Two Android Tips

Comments


Email:*
Name:*
Reqired fields are marked with a '*'