Setting Up Function Hooks in Lisp

Written by on May 29, 2022 in LISP, Programming with 0 Comments

Lisp is known to be a highly dynamic language, where functions are first-class objects. It is possible to define and undefine functions on the fly as well as attach hooks to existing functions. These are in addition to the ability to pass functions as parameters to other functions and returning a function as the result of a function call.

This article will explore some of these ideas in detail.

Getting the Function Object from Symbol

Let us start with a basic example:

Function Object

Function Example

Our bar” function takes two arguments and returns their sum. With this definition in place, we can get a handle to the function in many ways:

Getting A Handle to the Function

Getting A Handle to the Function

As you can infer, “#’bar” is actually a shortcut for the other two ways to get the function object.

How can we confirm that all three mean the same thing?

Confirming the Type

Checking the Type

And here is another check:

Confirming Equivalence

Confirming Equivalence

What the above show is that given a symbol, it is possible to get the function definition associated with that symbol (provided the function is defined).

Changing the Function Definition Dynamically

Lisp allows us to change any function definition at runtime. In our example, we can easily change the definition of “bar” shown earlier:

Changing Function Definition

Changing Function Definition

It is that simple. Of course, the old definition is lost now.

Defining “before” and “after” Hooks 

Changing the function definition at runtime is not common, although it is possible. However, many times, we might want to call a different function before and after the primary function is called. This can be useful in tracing the program flow, for example. How to do that?

Here is a naive implementation:

Managing Function Hooks

Managing Function Hooks

The set-function-hooks function uses a Hashtable to remember the original definition of the given a function and replace that definition with a function that applies the “before” and “after” functions appropriately while invoking the actual function. The remove-function-hooks function restores the original definition saved in the hashtable and removes the hashtable entry.

Here is an interaction showing how this works:

Function Hook Example

Function Hook Example

The reason why the given code is naive is because it allows only a single set of “before” and “after” functions to be attached. One can easily extend the logic to handle the general case.

Interestingly, Common Lisp already supports method combination, allowing us to attach “before, “after” and “around” auxiliary methods to primary methods. You can go through my article on Aspect-Oriented Programming in Lisp to see how this is done. Note that this is applicable only for methods and not for regular functions.

Defadvice Feature

LispWorks has a much richer way of attaching advice, i.e. executable code, to a function. It is possible to execute multiple auxiliary code “before”, “after”, or “around” a function. This permits arbitrary action(s) to be carried out in the context of a given function, method or macro.

Here is an example session:

Defadvice Example

Defadvice Example

The primary “foo” function doubles the argument. The “around” advice calls the original function and then adds 100 to the returned result. That is why we get 300 as the result when we call (foo 100). 

How to “undefine” a Function?

Common Lisp allows us to unbind (i.e. “undefine”) an existing function. Here is a sample session showing how this works:

Undefining a Function

Undefining a Function

That concludes our discussion on function hooks in Lisp. How you found the article useful. The sample code is available here.

Have a great weekend!

Tags: , ,

Subscribe

If you enjoyed this article, subscribe now to receive more just like it.

Subscribe via RSS Feed

Leave a Reply

Your email address will not be published.

Top