Clone this wiki locally
Dynamic recompilation is my own term for this fascinating configuration strategy. The core of the idea goes something like this:
- Write the main program functionality as a library.
- Write a very basic main function which simply calls the library with a default configuration.
Once this has been done, the end user can configure the program by simply creating a new program which imports the library and passes it a slightly different configuration. Of course, to call this data merely a ‘configuration’ demeans it, likening it to some flat file which can specify a paltry few options. By implementing the configuration in the source language, the user is given all the power that language has to offer. In Haskell, this means the user is free to define custom functions, IO actions, initialization and cleanup around the main program, and basically anything else they could imagine. Interestingly, Haskell is the only language that I have seen this strategy used in. I speculate that this is because it takes a language with the elegance and expressiveness of Haskell to make such configurations seem like anything other than a laughably verbose trick.
Of course, the application provides amenities to make this easier to use. Generally it will need to check for custom configurations, and then compile and run them if they are available. Another important feature is the ability to reload configurations while running. With a dynamic recompilation strategy, this must be achieved by writing a set of state information to disk, and then reloading it upon the initialization of the new program. In this way, the process of transforming their source program into executable code is made invisible to the user, to the point where they can simply forget about it if they wish.
Admittedly, dynamic recompilation can take longer on the first startup of the program, as it must compile and link an entire custom executable. The important thing to remember is that this is only a one-time cost, after which the program will run with unparalleled speed, because it no longer needs to read and parse a configuration file.
The end result of this strategy is a tremendously powerful configuration system, but the complex set of features can be difficult to implement flawlessly in every program. That’s where Dyre comes in.