Arc Forumnew | comments | leaders | submitlogin
Little languages
6 points by conanite 3087 days ago | 1 comment
I haven't completely grasped the whole hygiene debate yet, but here's a trick I would love some feedback on. This was inspired by the 100-year-language concept of just writing your program even if the compiler for it doesn't exist yet. I took the idea of a build script, as it's a domain that's fairly commonly understood and not too complicated. For java projects, "ant" is an almost universal default build tool, but its scripts are horribly verbose and difficult to extend. It seemed like a good target.

Anyway, that's a story for another day. One task of a build tool is finding sets of files (to copy, to compile, to delete). Ant abstracts this task as a "fileset". I wrote my arc-based script, and found I wanted to say

  ; copy all files under src/java except anything matching *.java
  (copy (files "src/java" (except "*.java")) wardir)

  ; copy files under lib/shipped, excluding the src directory, and
  ; excluding anything not matching *.jar
  (copy (files "lib/shipped" (except "src/") (only "*.jar")) libdir) 
Now, the problem is, it seems to be a pain to declare 'except and 'only as globally-accessible functions if their only purpose is to serve invocations of 'files. And what's more, 'only is already defined in arc.arc. I would like these two (and others, as they are invented) to be local only to their callers. And indeed, with a macro I can do this:

  (mac files (root . constraints)
    `(with (except (fn spec ...))
            only   (fn spec ...))
       (find-files ,root ,@constraints))
So the macro creates local bindings for 'except and 'only (just like aif does for 'it and afn does for 'self).

But I would like to allow you create more local bindings for 'files constraints, without obliging you to go patching my code. It's possible to do this, by maintaining a 'file-finder-plugins list.

  (set file-finder-plugins 
       (list 'except          (fn spec ...) 
             'only            (fn spec ...) 
             'my-constraint   (fn spec ...) 
             'your-constraint (fn spec ...)))
Now, 'files looks like

(mac files (root . constraints) `(with ,file-finder-plugins (find-files ,root ,@constraints))

This way, it's possible to inject the local bindings created by the macro, without having to touch the macro itself.

I haven't seen this trick elsewhere, so either I'm not reading enough, or it's considered evil. But it looks like a neat way to create little, local languages. It could be done for html too. Is there a verdict out there?

2 points by simonb 3087 days ago | link

Why not abstract the last bit away as well?

  (def-file-finder-plugin name (spec) ...)
As far as the approach itself is concerned I don't think it's evil. Just good use of declarative programming.