I originally come from Java land and have most of my experiences with languages and IDEs that include build systems, so the way your program is compiled has never been something I had to worry about. In Lisp too this is usually not that big of a deal thanks to ASDF, which lets you define which files depend on what and figures out how to compile and load it by itself. My problem with building Radiance is also a problem that is specific to Lisp and doesn't really occur in any other OO language.
What is it then that's so special about this case? As you might know, Lisp has a special feature that no other language really has: macros. Macros allow you to basically write your own syntax for the program and change how instructions are interpreted. To allow this sort of thing, the way programs are compiled has to be a bit different. Most importantly, any part of the project that references a macro first has to go through “macro expansion time”, at which point the macro is executed and the result is put in place of the macro call. Only then the function or statement can be actually compiled. As such, macros have to be defined before any function that uses a macro can be compiled. This requires a rather strict compilation sequence. Additionally, macros cannot be bound to classes so I cannot simply load different implementations for the same macro, as they'd be overwritten in the process even if only one implementation is active in the end.
As such I was driven to write a simple system that fixes these problems for me and allows me to simply load all the sources for whatever modules I want to have active at the time. To configure this system, an attribute in the settings file is required that maps implementation slots to modules. When the server is started up, the configuration is loaded and the module directory is scanned for any file with the .mod extension. This file is then compiled and loaded into the runtime. mod files should only contain module definitions, so that any module is visible to the system and can be fully loaded later. The module definition now contains two new values to make this system work, one that contains a list with implementations this module provides and another that provides the name of an ASDF system to load to compile this module. After all modules have been discovered, the implementations map in the configuration is iterated through and the required modules are compiled via ASDF.
This, along with the dependency options of the modules, allows me to load every implementation in the correct order so that all may compile correctly for the current setup. It's still a bit wonky right now and rather inflexible, but I'll see that it works as easily and smoothly as I can get it to be. Obviously such a system is not required for any standard program and ASDF alone will provide you with all necessary functionality to manage the build process.
I'm writing this mostly because I've had quite some headaches trying to get this system figured out. It was a lot more annoying to find a good solution than I ever anticipated. This seems to be a general theme in Lisp though. I spend considerably more time thinking about how to write the program than in any other language I've ever used. In any C-like I usually sit down, think about the OO architecture for a bit, lay out the base principles I want and then just start writing it all down. The writing of which takes far more time than anything else. In Lisp I often spend a lot of time just sitting back, thinking about what the best way would be to achieve what I want or analysing how the program currently works and how it could be improved, redistributed, refactored, restructured.
I think the reason for this different mindset to programming and problem solving is due to the degrees of freedom. In any other language you're pretty much limited to the language syntax and the libraries that are available to you. In Lisp however you have the freedom to do practically anything. There are so many ways to achieve the same thing, so many ways to improve upon a design, it is simply ridiculous. I'm not simply saying this because I'm fascinated by Lisp, but rather because I've been flabbergasted at how helpless I feel in certain situations. I simply have no clue which solution would be the best one in the long end, as I'm not limited by just what can be done. I admit that I'm still a complete newbie when it comes to programming in Lisp and a lot of my code could be drastically improved, I expect. But I am certainly not new to programming itself and this shift in attitude and mindset towards coding is just a lot to take in.
Lisp isn't simply different because of its (lack of) syntax, but more so because of the freedom it provides. As with anything, this is both a blessing and a curse. It is a magnificent feeling to get lost in the world of possibilities and simply letting ideas float around and do what you want to do. But at the same time it becomes so much more difficult to write a program the right way. Of course, there's never a single right way, but the question still remains as to which one is the best way for the long run and how to determine that ahead of time. Hopefully I'll get better at finding this out as I go along, but right now it is a rather frightening prospect.
Next up: Authentication, Session and User management.
Written by shinmera