Rerooting Frog
Frog wants to create blogs which hang directly under /
. I want mine to live under a subdirectory, and to have all its data living under that directory. I’ve made some changes to Frog to support that. As of 20150702 these changes have been merged to the main frog repo: you no longer need to refer to mine, which is obsolete.
What I did was to add a new parameter, uri-prefix
(implemented in the code as current-uri-prefix
) and write a function which converts between the original name and whatever external name is wanted: at the moment this just adds the prefix but it has ambitions. Most of the problem was then finding all the places where absolute URIs were assumed in the code, and I’m not sure I’ve done that — Racket does not seem to have very good tools for understanding the structure of any significant body of code, which I found surprising: perhaps I am spoiled by the very wonderful LispWorks code browsing tools.
These fixes could be found on GitHub, on the uri-root-fix
branch: this is no longer needed as improved versions are now in the main frog repo.
A theory of names
The underlying problem here is that you need a theory of names to do this sort of thing: rather than saying ‘things of type x live in /things/x/...
’ and then discovering that in fact they should live in /x/things/...
or something, the right answer is to keep the location in some representation which:
- doesn’t commit you to what the final pathname, URI or whatever is;
- has all the information you need to generate the final representation, including the ability to carry around completely arbitrary information;
- can not be confused for the final representation by the program.
Then you can write mapping functions, including extensible mapping functions, to invent the names you actually need from the objects you have.
Common Lisp’s logical pathnames are an early effort in this direction: they offer the ability to translate a logical pathname into a physical pathname in various ways. But they’re not the right answer simply because they are pathnames: they can (and are designed to) leak into functions which expect pathnames, and can also leak into places where strings are expected, since pathnames have representations as strings. It’s important that whatever representation is used for logical names is not compatible with code which wants, for instance, to emit URIs, so that you are forced to map things everywhere they are needed. In addition the mappings you can define for logical pathnames are not really general enough.
Note that it’s not enough to have a good approach to manipulating structured pathnames, URIs or whatever, because those are the wrong type of thing to manipulate.