Often happens it is useful not to write out calculated expression manually, and to generate it by means of the program. This idea of automatic dynamic programming is especially well realised in a 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 locking ('), for example, for the purpose of expression conversion. For calculation of the generated expression the programmer always can call the interpreter (eval). The special ways of processing of arguments provided in a Lisp open possibility for a combination of various methods.
The enumerated possibilities can be used in a Lisp and without special resources. However most naturally program creation of expressions is carried out by means of special macroes. Outwardly macroes are defined and used the same as functions, the way of their calculation differs only. Calculating macro call, at first from its arguments the form set by definition of a macro is under construction. As a result of call value of this form, instead of the form as would be at functions evaluation comes back. Thus, the macro is calculated as though in two stages.
Macroes represent the abstract mechanism with which help it is possible to define creation and calculation of any (computable) form or the whole program.
Macroes give the chance to expand syntax and semantics of a Lisp and to use new forms of sentences suiting for the solved task. Abstraction of such character name as abstraction of problem area, and the extension of language defined by them a Lisp - the built in language.
Macroes are a powerful working tool of programming. They give the chance to write the compact programs oriented to the task which will automatically be transformed to more complex, but effective code closer to the computer. However the difficulties and dangers too are linked to their usage. Forms created in the course of calculations are often difficult for seeing directly from definition of a macro or from the form of its call.
Syntax of definition of a macro looks the same as syntax used at definition of functions of the form defmethod:
(class-name defmacro macro-name arguments-list body)
Macro call coincides under the form with function call, but its calculation differs from function call calculation. The first difference consists that in a macro arguments are not calculated. The macro body is calculated with arguments in that sort as they are written. 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 a macro.
The second difference of a macro from function is linked to way of calculation of a body of a macro. Calculation of call of a macro consists of two by turns stages. At the first stage calculation of a body of definition with arguments from call in the same way, as well as for function is carried out. This stage name as a stage of the extension or macro disclosure as the arising form, as a rule, is more and more difficult the initial form of call. Often speak and about translation of macroes as at a stage of the extension the macrocall is assembled in some computable expression. At the second stage the opened form received from call which value comes back as value of all macrocall is calculated.
Let's define, for example, a macro setqq which works like setq, but locks calculation and the second argument:
>(nil setq list) nil >(nil defmacro setqq (x y) `(nil setq ,x ',y)) (macro (x y) `(nil setq ,x ',y)) >(nil setqq list (a b c)) ; setqq does not calculate the arguments (a b c) >list (a b c)
After a stage of the extension of macrocall value of a body of a macro was
(nil setq list '(a b c))
At the second stage this program created form is calculated by usual image and its value comes back as value of call of a macro. In this case the arisen form has a side effect.
So, the macro is a form which during calculation replaces on new, usually more complex form which then is calculated by usual image.
Arising during the macro extension new expression can contain again macrocall, probably recursive. Macrocalls containing in the extension lead at the second stage of calculations to new macrocalculations. By means of a recursive macro it is possible to carry out the extension dynamically depending on parametres, and proceeding macrocalculation. For example, copying of a top level of the list could be defined a following recursive macro:
>(nil defmacro copy ()) (macro nil) >('cons defmacro copy () (nil list nil 'cons ; call cons as the extension `',(this first) (nil list `',(this rest) 'copy))) (macro nil (nil list nil 'cons `',(this first) (nil list `',(this rest) 'copy))) >('(a b c) copy) (a b c)
As the first extension the expression containing new macrocall is formed:
(nil cons 'a ('(b c) copy))
Thus, the extension at the second stage of calculations leads to recursive macrocall. The recursion is ended on call (nil copy) which value of the extension is nil.
As at definition and function call, in case of macroes in lambda-list it is possible to use same &rest.
Parametre &rest it is used for instructions on in advance indefinite quantity of arguments. This mechanism is applied and to definition of the forms, not which all arguments need to be calculated or in which arguments are desirable for handling in the non-standard image. 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 don't suit.
Let's set the simple form cond by means of a following recursive macro:
(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 macro disclosure the considerable quantity of the calls of functions enclosed each other cons, first, rest, list, + and others is usually used. Therefore at extension construction it is possible to be mistaken easily, and the macrodefinition becomes less transparent. For simplification of a writing of macroes in a Lisp the special mechanism of locking of calculations as which name as return locking is accepted and which is marked unlike usual locking (') (return) apostrophe inclined in another side ` (back quote).
Inside back locked expression it is possible to cancel locally at will locking of calculations, differently in some subexpression again to carry out calculations. From here there is also a name of return locking. Locking cancellation is marked with a comma , before each subexpression intended for calculation. The comma gives possibility for a while to switch in a normal state 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 locking (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 return locking of expression from an anticipating comma replacing on their values. It is possible to name usage of an anticipating comma as substituting cancellation of locking. Except a comma it is possible to use a comma together with @ (at-sign) sign of joining of the subexpression. Expression before which there is a joining tag ,@, is calculated by usual image, but the received expression joins finite expression in the same way as it is made by function +. So external brackets of list value will disappear, and units become units of the list of a top level. Such form of cancellation of locking name connecting. We will give an example:
>(nil setq x '(new units)) nil >`(to include ,x in the list) ; substituting cancellation (to include (new units) in the list) >`(to include ,@x in the list) ; connecting cancellation (to include new units in the list)
Locking of calculations and cancellation signs are defined in a Lisp as reading macroes. To study ways of creation of expressions it is possible, setting the expression interpreter in which inside ' return locking contains. For example:
>'`(a (b ,c)) `(a (b ,c))
As value the hierarchy of calls of the system functions which calculation of value is interfered by an apostrophe turns out.
Back locking is a convenient resource of creation of a macro. With its help the macro can be defined in the form close to sort of its opened expression. For example, the macro list can be defined very simply:
(nil defmacro list (&rest args) (nil if (nil consp args) `(nil cons ,(args first) ,(nil list* nil 'list (args rest)))))
Back locking gives possibility 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 locking is used not only in macrodefinitions. For example, construction of results for function writeln often leads to usage of calls cons, list and other functions. We come nearer again with return locking to definitive output sort:
>('stream defmethod add-and (x y) (this writeln `(,x and ,y))) (lambda (x y) (this writeln `(,x and ,y))) >(cout add-and 'Bonnie 'Clyde) (bonnie and clyde) STREAM:Stdout
add-and would be possible to define and a following macro for which apostrophes before arguments are not necessary:
>('stream defmacro add-and (x y) `(,this writeln '(,x and ,y))) (macro (x y z) `(,this writeln '(,x ,y and ,z))) >(cout add-and Bonnie Clyde) (bonnie and clyde) STREAM:Stdout
The interesting type of macroes is derivated by macroes with a side effect, or the macroes changing definition. As, changing, they simultaneously delete something, them still name structure-destroying as macroes.
By means of a suitable side effect it is often possible to receive more effective solution both in macroes, and in operation with structure-destroying functions. However to use them it is necessary very attentively, differently the received effect becomes for the program destroying in literal sense of this word.
Usually the Lisp interpreter expands macrocalls at each call anew, that in some situations can be too ineffective. Programming of such macro with engaging of a side effect can become alternative solution, which substitutes by means of pseudo-functions ( setfirst, setrest, etc.) macrocall on its extension. Such macroes are not present need to expand each time as by following call of a macro on a macrocall place there will be an extension received by the first call. For example:
>('cons defmacro the-first () `(',this first)) (macro nil `(',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 at each function call write-first is made the macro extension the-first:
>('(a b c) write-first) a STREAM:Stdout
Let's transform now a macro the-first in structure-destroying a macro:
('cons defmacro the-first (&whole expression) ((expression rest) setfirst 'first) expression)
The macro extension happens now only at the first function call write-first, which as a side 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 defined in sort:
('cons defmethod write-first () (cout writeln (this first)))
Except syntactic definition of forms macroes are applied and to definition of new methods. We have already got acquainted with the main data types of a Lisp: numbers, symbols and lists. Further we as the elementary example of application of macroes for operation with data types will set a macro defaccess which defines intended for reading of property of the character the elementary function of the access which name is this property, and argument - the symbol. By means of such function of access it is possible to read property of the symbol in more simple form, than by means of the form get, namely
; Macro of definition of function of access ('symbol defmacro defaccess () `('symbol defmethod ,this () (this get ',this)))
As a result of call of a macro we as a side effect will receive definition of a new method with the help defmethod.
>('apple put 'color 'red) ; property assignment red >('color defaccess) ; definition by means of an access macro (lambda nil (this get 'color)) >('apple color) ; property reading became easier now red
By means of macroes it is possible to write easily programs which form other programs and at once calculate them.