3 ms·
I very much agree with this article. Reminds me of the evolution of my lisp HTML compiler. At first I simply made a macro that transforms: (:tag :attribute
by Hexstream 19y ago
I very much agree with this article.
Reminds me of the evolution of my lisp HTML compiler. At first I simply made a macro that transforms:
(:tag :attribute "value" (:p "Paragraph"))
into appropriate code to output the HTML at runtime. But the problem is that I couldn't inspect or transform my HTML; this macro-based scheme was way too brittle.
So instead I wrote another macro with the same syntax but that instead generates code to build a semantic representation of HTML at runtime:
(make-instance 'html-node :type "tag" :attributes (cons "attribute" "value" :children (list (make-instance 'html-node :type "p" :children (list "Paragraph")))))
I then pass this representation to a compiler that first optimizes ("flattens" the structure and appends contiguous strings together) and then compiles into an efficient tree of closures. I still have a version of the macro that generates efficient code to output the HTML directly that I use in my dynamic HTML generation functions, but I use that only when necessary.
The advantage is that now I can do all sorts of static analysis on my HTML (I use a similar scheme for CSS). Believe it or not, in a "dynamic" site there's TONS of static (as in, known before someone even tries to access the page) information. I even have a scheme to "inject" stuff into pages, for example the (page-sensitive) navigation is automatically "baked" into the appropriate pages.
Eventually I want to make a "site debugger" with all the semantic data I have about my site. I'll have powerful querying capabilities to answer questions like: "What pages in my site have an A tag that links to page X and is nested in a container affected by CSS rule Y?". Maybe I can even make some kind of advanced editor. Owning your data opens lots of interesting possibilities indeed!
So, I get all the semantic data plus the great speed. The best of both worlds. I think this really illustrates the importance of compilers and of languages like lisp that facilitate their implementation. I never made a low-level compiler and it will be some time before I'm knowledgeable enough to make one but lisp allowed me to make those high-level HTML and CSS compilers comparatively easily.
Another important thing is separating policy from mechanism, one obvious problem of the programmer that represented rules directly in code as depicted in the article is that he hard-coded policy into his program, but the thing is that policy is volatile so it really belongs in a config file.
I think this somewhat resonates with the quote: "Programs must be written for people to read, and only incidentally for machines to execute." Except programs themselves often want to read programs for the purpose of analysis or manipulation, hence the advantage of representing the most logic you can in a "dumb" language or data format.