Often happens it is useful to not write out calculated expression manually, and to generate it by means of the program. This idea of automatic dynamic programming is especially well realized in Lisp as the program in this language also is represented in the form of the list. Thus calculation of such expression or its part if necessary can be prevented blocking (quote), for example, with the purpose of transformation of expression. For calculation of the generated expression the programmer always can cause the interpreter (eval). Stipulated in Lisp special ways of processing of arguments open an opportunity for a combination of various methods.
The listed opportunities can be used in Lisp and without special means. However most naturally program formation of expressions is carried out by means of special macros. Externally macros are defined and used the same as functions, the way of their calculation differs only. Calculating a call of macros, all over again from its arguments the form set by definition macros is under construction. As a result of a call value of this form, instead of the form as would be at function evaluation comes back. Thus, macros is calculated as though in two stages.
Macros represent the abstract mechanism by means of which it is possible to define formation and calculation of the any (computable) form or the whole program.
Macros enable to expand syntax and Lisp semantics and to use new forms of offers suitable for a solved problem. Abstraction of such character name abstraction of problem area, and expansion of Lisp language defined by them - the built in language.
Macros is a powerful working tool of programming. They enable to write the compact programs focused on a problem which will automatically be transformed to more complex, but closer to the machine effective Lisp code. However the difficulties and dangers too are connected with their use. Forms created during calculations are often difficult for seeing directly from macros definition or from the form of its call.
Syntax of macros definition looks the same as syntax used at definition of functions of the form defmethod:
(class-name defmacro macros-name arguments-list body)
The macros call coincides under the form with a call of function, but its calculation differs from calculation of a call of function. The first difference consists that in macros arguments are not calculated. The macros body is calculated with arguments in that kind as they are written down. Methods always preliminary calculate the arguments and if there is a necessity that the argument was not calculated, such forms are defined by means of macros.
The second difference macros from function is connected with way of calculation of a macros body. Calculation of a call of macros consists of two consecutive stages. At the first stage calculation of a body of definition with arguments from a call in the same way, as well as for function is carried out. This stage name a stage of expansion or disclosing of macros as the arising form, as a rule, is more and more difficultly than the initial form of a call. Often speak and about translation of macros as at a stage of expansion the macrocall is broadcast in some computable lisp expression. At the second stage the opened form received from a call which value comes back as value of all macroses is calculated.
Let's define, for example, macros setqq which operates like setq, but blocks calculation and the second argument:
>(nil setq list)
NIL
>(nil defmacro setqq (x y)
(nil list nil 'setq x (nil list nil 'quote y)))
(macro (x y) (NIL list NIL (NIL quote setq) x (NIL list NIL (NIL quote quote) y)))
>(nil setqq list (a b c)) ; setqq does not calculate the arguments
(a b c)
>list
(a b c)
After a stage of expansion of a macrocall value of a macros body was
(nil setq list (nil quote (a b c)))
At the second stage this the programmed created form is calculated by usual mode and its value comes back as value of a call macros. In this case the arisen form has a by-effect.
So, macros is a form which during calculation is replaced on new, it is usual more complex form which then is calculated by usual manner.
Arising during expansion of macros new expression can contain again a macrocall, probably recursive. Macrocalls containing in expansion lead at the second stage of calculations to new macrocalculations. By means of recursive macros it is possible to carry out the expansion dynamically depending on parameters, and a proceeding macrocalculation. For example, copying of top level of the list could be defined the following recursive a macros:
>(nil defmacro copy ())
(macro NIL)
>('cons defmacro copy ()
(nil list nil 'cons ; call cons as expansion
(nil list nil 'quote (this first))
(nil list (nil list nil 'quote (this rest)) 'copy)))
(macro NIL (NIL list NIL (NIL quote cons) (NIL list NIL (NIL quote quote) (this first)) (NIL list (NIL list NIL (NIL quote quote) (this rest)) (NIL quote copy))))
>('(a b c) copy)
(a b c)
As the first expansion the expression containing a new macrocall is formed:
(nil cons (nil quote a) ((nil quote (b c)) copy))
Thus, expansion at the second stage of calculations leads to a recursive macrocall. Recursion comes to an end on a call (nil copy) which value of expansion is nil.
As at definition and a call of function, in case of macros in the lambda-list it is possible to use the same keyword &rest.
The parameter &rest is used for the instruction on in advance not certain quantity of arguments. This mechanism is applied and to definition of forms, not all which arguments needs to be calculated or in which arguments are desirable for processing in the non-standard manner. For example, in the usual form cond predicates are calculated only until the first value which is distinct from nil and false will be received. For definition of such forms of function do not approach.
Let's set the simple form cond by means of the following recursive macros:
(nil defmacro cond (&rest branches)
(nil if (nil consp branches)
(nil let ((branch (branches first)))
(nil if (nil eval (branch first))
(nil list* nil 'progn (branch rest))
(nil list* nil 'cond (branches rest))))))
At disclosing of macros a plenty of the calls of functions enclosed each other cons, first, rest, list, + and others is usually used. Therefore at construction of expansion it is possible to be mistaken easily, and the macrodefinition becomes less transparent. For simplification of a writing of macroses in Lisp the special mechanism of blocking of calculations which name return blocking is accepted and which is marked unlike usual blocking (quote) (back) quote inclined in another party ` (back quote).
Inside back blocked expression it is possible to cancel locally at will blocking of calculations, differently inside of some subexpression again to carry out calculations. From here there is also a name of return blocking. The cancelling of blocking is marked with a comma , before everyone intended for calculation subexpression. The comma enables for a while to be switched in a normal condition of calculations. An example:
>'(is not calculated (3 + 4)) ; ordinary ' it is not cancelled
(is not calculated (3 + 4))
>`(is possible to calculate (3 + 4)) ; ` operates as usual blocking
(is possible to calculate (3 + 4))
>`(is desirable to calculate ,(3 + 4)) ; , before expression leads to its calculation
(is desirable to calculate 7)
In expanded expression at back blocking expression from an anticipating comma are replaced with their values. Use of an anticipating comma can be named replacing cancelling of blocking. Except for a comma it is possible to use a comma together with a sign @ (at-sign) connections subexpression. Expression before which there is an attribute of connection ,@, is calculated by usual manner, but the received expression joins final expression in the same way as it is done with function +. So external brackets of list value will be gone, and elements become elements of the list of top level. Such form of a cancelling of blocking name attaching. We shall give an example:
>(nil setq x '(new elements))
(new elements)
>`(to include ,x in the list) ; replacing cancelling
(to include (new elements) in the list)
>`(to include ,@x in the list) ; attaching cancelling
(to include new elements in the list)
Blocking of calculations and signs on a cancelling are defined in Lisp as macros readings. To study ways of formation of expressions it is possible, setting the interpreter of expression in which inside quote contains back blocking. For example:
>'`(a (b ,c))
(NIL backquote (a (b (NIL unquote c))))
As value the hierarchy of calls of system functions which calculation of value is interfered by an apostrophe turns out.
Back blocking is convenient means of formation of macros. With its help macros is possible to define in the form of, close to a kind of its opened expression. For example, macros list is possible to define very simply:
(nil defmacro list (&rest args)
(nil if (nil consp args)
`(nil cons ,(args first)
,(nil list* nil 'list (args rest)))))
Back blocking enables to define the opened expression in the form of the sample in whom dynamically filled forms are marked by a comma. It helps to avoid a complex combination of calls of functions cons, list and others.
Back blocking is used not only in macrodefinitions. For example, construction of results for function writeln often leads to use of calls cons, list and other functions. With back blocking we again come nearer to a final deduced kind:
>('stream defmethod add-and (x y)
(this writeln `(,x and ,y)))
(lambda (x y) (this writeln (NIL backquote ((NIL unquote x) and (NIL unquote y)))))
>(cout add-and 'Bonnie 'Clyde)
(bonnie and clyde)
STREAM:Stdout
add-and would be possible to define and the following a macros for whom apostrophes before arguments are not necessary:
>('stream defmacro add-and (x y)
`(,this writeln '(,x and ,y)))
(macro (x y) (NIL backquote ((NIL unquote this) writeln (NIL quote ((NIL unquote x) and (NIL unquote y))))))
>(cout add-and Bonnie Clyde)
(bonnie and clyde)
STREAM:Stdout
Interesting type of macroses form macros with a by-effect, or macros, changing definition. As, changing, they simultaneously destroy something, them still name structure-destroying macro.
By means of a suitable by-effect it is often possible to receive more effective decision both in macros, and in work with structure-destroying functions. However to use them it is necessary very closely, differently the received effect becomes for the program destroying in literal sense of this word.
Usually Lisp interpreter expands macrocalls at each reference anew, that in some situations can be too inefficient. The alternative decision can become programming such macros with attraction of a by-effect, which replaces by means of pseudo-functions (setfirst, setrest, etc.) a macrocall with its expansion. Such macros there is no need to expand each time as by a following call of macros on a place of a macrocall there will be an expansion received by the first call. For example:
>('cons defmacro the-first ()
`((nil quote ,this) first))
(macro NIL (NIL backquote ((NIL quote (NIL unquote this)) first)))
>('(a b c) the-first)
a
>('cons defmethod write-first ()
(cout writeln (this the-first)))
(lambda NIL (cout writeln (this the-first)))
By these definitions by each call of function write-first macros expansion of the-first is made:
>('(a b c) write-first)
a
STREAM:Stdout
Let's transform now macros the-first in structures destroying macros:
('cons defmacro the-first (&whole expression)
((expression rest) setfirst 'first)
expression)
Macros expansion occurs now only by the first call of function write-first, which as a by-effect will transform the form (this the-first) in a body write-first to the form (this first). Calculations correspond to a situation in which write-first it would be from the very beginning certain in the form of:
('cons defmethod write-first ()
(cout writeln (this first)))
Except for syntactic definition of forms macroses are applied and to definition of new methods. We have already got acquainted with the basic types of Lisp data: numbers, symbols and lists. Further we as the elementary example of application of macroses for work with types of data shall set macros defaccess which defines intended for reading property of a symbol the elementary function of access which name is this property, and argument - a symbol. By means of such function of access it is possible to read property of a symbol in more simple form, than by means of the form get, namely
(symbol property)
; Macros of definitions of function of access
('symbol defmacro defaccess ()
`('symbol defmethod ,this ()
(this get ',this)))
As a result of a call of macros we as a by-effect shall receive definition of a new method by means of defmethod.
>('apple put 'color 'red) ; giving the property
red
>('color defaccess) ; definition by means of access macros
(lambda NIL (this get (NIL quote color)))
>('apple color) ; reading of property now became easier
red
By means of macros it is possible to write easily programs which form other programs and at once calculate them.