Macros are to this day still unique to lisp (there are languages which employ macros, but there are either simple textreplacing macros like in C
or in languages that are even more underground than Lisp).
In Paul Grahams book "On Lisp" he desribes 3 things macros do that are impossible with functions:
1) Conditional Evaluation
2) Lexical Context
3) Setf Accessor
I might add
4) Compiler macros
Compiler macros are a good way to shift runtme.-computations to compile-time computations and therefore increase speed.
Setf-accessors are important for Lisp but Python provides the variable = expression assignment and good control over objects with the magic __setattr__ methods.
That leaves the main point about macros: Conditional evaluation and lexical context. The main thing to remember about macros is that they can execute a (code) body. In Python you have to use the builtin compound statements like if, for and with. In Lisp you can create new control flow instruments that execute a given body n-times, depending on condition y and other magic stuff. Take the "conditional jump" example earlier this thread. It is easy for python to keep up when only short expression are involved.
But lets construct a more detailed example: You are given a list of points which represent geometrical figures. If the list include only 2 points, it is a line, if it includes 3 point it represents a triangle and four point represent a rectangle. You want to write a function that calculates the area of these figures. In Python you have to use the "native" control structures
Code: Select all
def area (*args): # &rest arg in Lisp
if (len(args) == 2):
if (len (args) == 3):
return (0.5 * dist (args, args) * calc_height (args, args, args))
In lisp you can make a specific control structure that takes a list argument and 3 different code bodies and completly abstracts the python if... if.. clauses.
Code: Select all
(my_macro input 0 (* 0.5 (dist (first input) (second input)) (height_calc (first input) (second input) (third input))) rectangle_calc)
Another thing are the lexical enviroment macros, which bind certain variables while the code body is evaluated. I think this is easily replicated in Python by using a function that takes a object and returns a dictionary with certain properties of the object. It is useful if combined with the conditional evaluations macros and can create for example an anaphoric-if.
The big question is "Is it worth it?". My answer is no, I choose Python over Lisp. Macros arent compelling enough to make a difference for me, because they are difficult to write and I dont need additional control structures beyond a well designed core. You often hear the following arguments from lisp coders: "What if they take away your if and with statement tomorrow and you only have AND and OR left? What would you do then without macros?". That is a pointless argument. Because python has no possibilities to create basic structures from scratch it ships with the (well rounded) builtins.