There have been a few conversations about instrumentation libraries on the list, and I've been experimenting with the features Ulf recently added to parse_trans. I've worked up a simple annotations library, that let's you put attributes/annotations on specific functions and attach behaviour to them in the form of an implementation module. The current framework is very crude and relies on a compile time parse transform, though obviously it'll be relatively trivial to implement runtime code changes as well.<div>
<br></div><div>The purpose of this prototyping was to play around with some of the ideas in Aspect Oriented Programming, and the library allows you to write code that executes before, after or around an annotated function. This is done without macros, which feels a bit neater to me than the approach used in erlang-web. In addition to the library, I've made a small reference project which implements a simple function memoization annotation using ets as a cache. The implementation of the annotation itself is very simple:</div>
<div><br></div><div>-module(memoize).</div><div>-annotation('function'). %% scoped to functions</div><div>-export([init/1]).</div><div>-export([around_advice/4]).</div><div><br></div><div>init(Module) -></div>
<div> ets:new(Module, [ordered_set, public, named_table,</div><div> {write_concurrency,true},</div><div> {read_concurrency,true}, compressed]),</div><div> ok.</div><div><br></div>
<div>around_advice(_A, M, F, Inputs) -></div><div> case ets:lookup(M, {F, Inputs}) of</div><div> [] -></div><div> Result = annotation:call_advised(M, F, Inputs),</div><div> true = ets:insert_new(M, {{F, Inputs}, Result}),</div>
<div> Result;</div><div> [{_, Memoized}] -></div><div> Memoized</div><div> end.</div><div><br></div><div>And the usage of the annotation is very simple too:</div><div><br></div><div><div>
-module(fib_mem).</div><div>-export([start_memoize/0, fib/1]).</div><div>-include_lib("annotations/include/annotations.hrl").</div><div><br></div><div>start_memoize() -></div><div> memoize:init(?MODULE).</div>
<div><br></div><div>-memoize(ets).</div><div>fib(0) -> 0;</div><div>fib(1) -> 1;</div><div>fib(N) -> fib(N - 1) + fib(N - 2).</div></div><div><br></div><div>--------------------</div><div><br></div><div>As I said, the implementation is very crude but I hope that the concepts will trigger some discussion about whether this is a useful contribution and in what directions it ought to go.</div>
<div><br></div><div>Code is here: <a href="https://github.com/hyperthunk/annotations">https://github.com/hyperthunk/annotations</a></div><div>Memoize is here: <a href="https://github.com/nebularis/memoize">https://github.com/nebularis/memoize</a></div>