Confused by Lisp Quote
I have a question regarding the evaluation of lists in lisp.
(+ a 1)
(defun test (a) (+ a 1))
is not evaluated here
(if (< 1 2) (print 3) (print 4))
(print (+ 2 3))
(test (print (+ 2 3)))
Does it have anything to do with them, being standard library functions? Is it possible to define such functions in my lisp program?
source to share
As you probably know, Lisp compound forms are usually processed from the outside to the inside. You have to look at the symbol at the first position of the outermost nest to understand the shape. This symbol completely defines the meaning of the form.
;; Common Lisp: define a class A derived from B and C (defclass a (b c) ()) ;; Common Lisp: define a function of two arguments (defun a (b c) ()) ;; add A to the result of calling function B on variable C: (+ a (b c))
Traditionally, Lisp dialects divide forms into operator forms and function call forms. The form of an operator has a completely arbitrary meaning, determined by a piece of code that compiles or interprets these functions (for example, the estimate is simply recalculated across all forms of function call arguments, and the resulting values are passed to the function).
Since its early history, Lisp has allowed users to write their own operators. There were two approaches to this: interpretive statements (historically known as
) and compiling statements known as macros. Both are based on the idea of a function that takes an invaluable form as an argument so that it can implement a custom strategy, thereby extending the scoring model with new behaviors.
simply submits the form at runtime along with an environment object with which it can search for variable values, etc. This operator then scans the form and implements the behavior.
The form is passed to the macro operator at the time of macro expansion (which usually happens when reading top-level forms just before they are evaluated or compiled). Its job is not to interpret the behavior of the form, but instead to translate it by generating code. That is, a macro is a mini-compiler. (The generated code may contain more macro calls; the macro scoper takes care of this, ensuring that all macro calls are destroyed.)
The approach has fallen
out of use, most likely because it is ineffective. This basically makes it impossible to compile, whereas Lisp hackers evaluate compilation. (Lisp was already a compiled language around 1960.) The approach is
also hostile to lexical environments; it requires
which is a function to insert into the variable binding environment the form in which it is called, which is a kind of encapsulation violation that is not allowed by lexical scopes.
Macro writing is a little more complex and in some ways less flexible than fexprs, but macro support improved in Lisp before 1960 to 70 to keep it as close to the bare minimum as possible. The macro initially received the entire form, and then parsed it himself. The macro definition system has evolved into something that provides macro functions with arguments that get broken syntax in easy-to-digest parts, including some nested syntax aspects. A backquote syntax for writing code templates has also been developed, making it much easier to express code generation.
So, to answer your question, how can I write similar forms? For example, if:
;; Imitation of old-fashioned technique: receive the whole form, ;; extract parts from it and return the translation. ;; Common Lisp defmacro supports this via the &whole keyword ;; in macro lambda lists which lets us have access to the whole form. ;; ;; (Because we are using defmacro, we need to declare arguments "an co &optional al", ;; to make this a three argument macro with an optional third argument, but ;; we don't use those arguments. In ancient lisps, they would not appear: ;; a macro would be a one-argument function, and would have to check the number ;; of arguments itself, to flag bad syntax like (my-if 42) or (my-if).) ;; (defmacro my-if (&whole if-form an co &optional al) (let ((antecedent (second if-form)) ;; extract pieces ourselves (consequent (third if-form)) ;; from whole (my-if ...) form (alternative (fourth if-form))) (list 'cond (list antecedent consequent) (list t alternative)))) ;; "Modern" version. Use the parsed arguments, and also take advantage of ;; backquote syntax to write the COND with a syntax that looks like the code. (defmacro my-if (antecedent consequent &optional alternative) `(cond (,antecedent ,consequent) (t ,alternative))))
This is an example because initially Lisp only had
. There was no
Lisp in McCarthy . This "syntactic sugar" was invented later, probably as a macro expanding to
, as above
source to share
- macros. Macros expand the form to a longer piece of code. During expansion, none of the arguments to the macro are evaluated.
When you try to write a function but struggle because you need to implement your own evaluation strategy, its a strong signal that you should write a macro.
Disclaimer: Depending on what type of lisp you are using
can technically be called "special forms" rather than macros, but the concept of lazy evaluation still applies.
source to share
Lisp consists of a form evaluation model. Different dialects of Lisp have different rules for them.
Let's take a look at Common Lisp.
- the data is self-evaluated
- the form of the function is evaluated by calling the function on the evaluated arguments
- special forms are evaluated according to the rules defined for each special operator. The Common Lisp standard lists all of them, defines what they do in an informal way, and there is no way to define new special operators by the user.
- the forms of macros are converted, the result is evaluated
How IF, DEFUN, etc. work, and what they evaluated when it is doen and what is not evaluated is defined in the Lisp standard.
source to share