User Tools

Site Tools


ch2_1_defmacro

DEFMACRO

DEFMACRO form defines a macro in global scope. It needs at least one symbol argument, which is not evaluated and will be the name of the macro. Second argument must be a list of parameters (symbols) of the macro, the symbols are not evaluated and will be used for local binding of parameters once the macro is called. Just like in DEFUN, no parts of the DEFMACRO expression are evaluated during the definition. Third argument is optional description string. If the third argument is not string, it is considered first form of the macro body. Any other parameters are to DEFMACRO are stored as the macro body.

The syntax of DEFMACRO is the same as DEFUN, because the object created is a macro-expansion function - a function that produces code. The difference between function and macro only takes effect when the macro or function is called. Arguments to macro call are not evaluated automatically, and they are supplied to the macro-expansion functions as forms. The macro itself takes control over the evaluation of the arguments. Output of the macro-expansion function should be code - a form that will be evaluated afterwards.

Function and macro names are in the same namespace. When defining macro with the same name as existing function, LabLISP will just inform the user, the previous function definition will be dropped and the symbol will refer to macro.

As example we define macro for adding, just as trivial as in the example for DEFUN

>(defmacro adder (a b)  ; macro named ADDER, arguments A, B
   “replaces plus”       ; optional description string 
   `(+ ,a ,b))           ; quoted form, unquoted A, B
ADDER                   ; DEFMACRO returns the symbol naming the new macro   

When called, we just receive the expected result:

>(adder 1 3)
4

What happens during the call is that the arguments 1 and 3 were supplied to the macro-expansion function, which produced a list (+ 1 3), using the BACKQUOTE and UNQUOTE operators. Only after, this list is evaluated as form, and gives the result.

In the following example, we call the macro with the forms (- 2 1) and (+ 2 1) as parameters. The macro code will receive the forms, not the results of those, as would be the case in function call.

>(adder (- 2 1) (+ 2 1))
4

In the macro-expansion function, the UNQUOTE operations evaluate the symbols A and B as the forms (- 2 1) and (+ 2 1), so the expansion function produces code (+ (- 2 1) (+ 2 1)) and that is evaluated at the end.

One can inspect the result of macro-expansion functions with MACRO-EXPAND:

>(macro-expand '(adder (- 2 1) (+ 2 1)))  ; supply quoted code to MACRO-EXPAND function
(+ (- 2 1) (+ 2 1))   ; result of the expansion

Optional parameters

Analogically to functions, the parameter list of DEFMACRO can have &OPTIONAL and &REST parameters (see DEFUN). In DEFMACRO it is possible to use &WHOLE parameter as first parameter, before any mandatory paramters. The &WHOLE parameter is not counted to the number of parameters, and will be bound to the whole list of supplied arguments, when the macro is called.

Following example defines macro for 2 arguments:

>(defmacro bar (&whole c a b) `(progn (print ',c) (+ ,a ,b)))
BAR
USER>(bar 2 3)
(2 3)            ; the whole list of arguments is printed
5 

In DEFMACRO, the keyword &BODY can be used instead of &REST, but they have exactly the same meaning in LabLISP.

See also: MACRO-EXPAND, MACROLET, SYMBOL-MACROLET

ch2_1_defmacro.txt · Last modified: 2022/03/31 05:39 by admin

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki