Deleting a macro

I sometimes run into a situation with Hy that I would like to delete a macro. This happens especially when I’m trying to get a feel of code and are prototyping in REPL. Functions are easy to delete and replace with macro, but other way around took a bit digging.

Macros are functions that often are used to write pieces of code for you. They usually accept code as parameters and emit different code back. When Hy compiler encounters a macro, it calls the respective function and replaces macro with the its output. This is called macro expansion and is done as long as the output contains something to expand. After all, nothing stops users writing macros that output code containing macros that need to be expanded. Macros are also namespaced, so you can define two macros with same name in different modules and there won’t be a collision.

All macros that have been defined live in a special place: hy.macros.-hy-macros. This dictionary contains more dictionaries, each representing a namespace containing macro functions. Strings are used as keys in both cases. The special namespace called __console__ (note the usage of underscores instead of hyphens, these names are mangled contains macros defined in REPL. Peeking inside, we can see their names:

=> (get hy.macros.-hy-macros "__console__")
{'ideas': <function ideas_macro at 0xb6b83a04>, 
 'koan': <function koan_macro at\  0xb6b83adc>, 
 'ap_each': <function _hy_anon_fn_2 at 0xb6a3fe84>}

ap-each is there, because I had required it in my REPL session. ideas and koan are sort of easter eggs that come with Hy. You can run them to see what happens.

Any macro defined here is available in REPL session. While it’s possible to modify this dicrionary with usual Hy functions, it’s easier to define a little helper function:

(defn del-macro [macro-name &optional namespace]
  (if namespace
    (del (get (get hy.macros.-hy-macros namespace) macro-name))
    (del (get (get hy.macros.-hy-macros "__console__") macro-name))))

This function removes macro definition from the dictionary. Parameters are name of the macro to remove and optional namespace. If namespace isn’t provided, __console__ will be used (that’s the most common use case for me anyway).

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s