11

I have been reading about the libraries people have written for languages like Java and C# that make use of byte code weaving to do things like intercept function calls, insert logging code, etc. I have also been reading up on Lisp/Clojure macros in an attempt to better understand how to utilize them. The more I read about macros, the more it seems like they provide the same kind of functionality as byte code weaving libraries. By functionality, I mean the ability to manipulate code at compile time.

Examples of libraries I have been looking at would be AspectJ, PostSharp, and Cecil.

Is there anything that can be done with one and not the other? Do they actually solve the same problems or am I comparing apples and oranges?

2
  • 2
    byte code weaving is a work-around when you need a dynamic language but are stuck with a statically typed language Commented Mar 31, 2013 at 23:25
  • 2
    @kevincline are you seriously trying to start up this old fight? Commented Apr 1, 2013 at 4:16

3 Answers 3

9

Byte code weaving and macros are two different things.

Byte code weaving is a way to intercept function calls, so that you can inject some sort of functionality (generally a cross-cutting concern such as logging) into a function call, either before or after the function is executed. Byte code weaving is done at the byte code level, which means that it occurs after compilation. The function itself is not affected. This is one of the techniques that Aspect Oriented Programming uses.

Macros are a way to extend the syntax of a language. In its simplest form, a macro is simply a way to record keystrokes, and then play them back using a hot key. Language macros work in a similar fashion; a keyword or other syntax construct substitutes for some sort of macro expansion. This is oversimplified, of course; a better example of a macro specific to Lisp can be found here.

6
  • +1 for mentioning that this is a key way of implementing AOP. Commented Apr 1, 2013 at 4:13
  • And transactions... let us not forget transactions. Commented Apr 1, 2013 at 4:17
  • 3
    LISP macros are nothing like 'a way to record keystrokes'. Commented Apr 2, 2013 at 20:18
  • 1
    Well some fundamental concepts are missing to the answer IMO, those could be: AST, reflection, Metacircularity. Commented Apr 3, 2013 at 8:51
  • 2
    @AndreasScheinert: The OP didn't ask about any of those things. This isn't a dissertation; it's just an answer to the OP's question. Commented Apr 3, 2013 at 14:24
5

Although they may be used to the same end, LISP macros are quite different from Java byte-code weaving plugins. LISP macros extend LISP syntax at the LISP source code level. Since LISP macros are written at the same level as other LISP code, they are a commonly used language feature.

Java byte-code weaving plugins operate at the JVM level. While many Java programmers may use byte-code weaving plugins written by others, very few Java programmers write their own byte-code weaving plugins.

Some of the work done by Java compiler plugins is very easily done in dynamic languages. Function-call interception is particularly simple.

2
  • I understand the technical differences between the two. I was attempting to look at the question from a high level point of view. Can both tools manipulate code to achieve the same goals? Are there any problems that macros can not solve that bytecode manipulation can (in a sane and cost efficient manner)? That is more what I was going for. Commented Apr 3, 2013 at 3:12
  • @mortalapeman: the manipulations possible in Java and C# via byte-code modification can all be done directly in languages like Lisp, Ruby, Python, Lua, Javascript... It is presumably possible to do everything that a LISP macro can do via byte-code manipulation, but in practice that does not happen. Commented Apr 3, 2013 at 3:33
4

Lisp macros are operating at the source code level. If you wrap some macro around a piece of code, then you can do a lot of things. Including parsing the source code, inserting code, rewriting code, etc.

If you want to modify function calls, Lisp usually uses two mechanisms:

  • late binding symbols. You can modify the function bound to a symbol. Every function calling which goes through a symbol, then uses the new function.

  • Lisp implementations sometimes provide a feature called 'advice'. This allows to execute code before, after or around calls. For example in LispWorks: Advice.

Thus you can intercept calls without low-level code manipulation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.