Sometimes within my own code I'd like to use a shorter or different name for a function or macro that I'm using or defining, even if I don't want those names to be the ones I have to use everywhere. For example, I may be writing a function that's used within a library, so I give it a long name to avoid possibly conflicting with the name of some other function that someone else may have written: (def pr-python-string (s)
(pr #\')
(escape-python-string s)
(pr #\'))
but I may prefer not to have to type such long names.Or perhaps I may wish to be using my own versions of macros like "case" or "loop", but I don't have the need or desire to change all code everywhere to use my version. Many languages have modules to provide namespace separation, and some allow imports and exports to be renamed. However, modules often seem overly bureaucratic to me, so I was wondering what it would like to be able to do just the renaming feature. First a extension of Arc's tree-subst to take an association list of the atoms to replace in a tree: (def tree-substs (substs tree)
(if (atom tree)
(aif (alref substs tree)
it
tree)
(cons (tree-substs substs (car tree))
(tree-substs substs (cdr tree)))))
arc> (tree-substs '((a X) (e Y)) '((a b (c d) ((e) f))))
((X b (c d) ((Y) f)))
And then a macro to perform substitutions within code: (mac abbrev (substs . body)
`(do ,@(tree-substs (eval substs) body)))
arc> (abbrev '((str string))
(str 1 2))
"12"
The substitutions are done blindly, taking no notice as to whether the symbols being replaced are quoted, or special syntax, or anything else. arc> (abbrev '((optional o) (foo bar))
((fn ((optional x 'foo)) x)))
bar
The list of substitutions is eval'ed during the macro expansion so that its value may be a calculated one. (def prefix (x xs)
(map [list _ (sym (string x _))] xs))
arc> (prefix 'python- '(escape-string pr-string))
((escape-string python-escape-string) (pr-string python-pr-string))
(abbrev (prefix 'python- '(escape-string pr-string))
...
(def pr-string (s)
(pr #\')
(escape-string s)
(pr #\'))
)
I haven't used this yet in real code so I don't know if I'll actually like it, but it seemed like an interesting enough idea to share. |