Are Lisp forms and Lisp expressions same thing?

2019-03-23 08:51发布

问题:

Some literature say "the first subform of the following form..." or "to evaluate a form..." while some other literature say "To evaluate an expression...", and most literature seem to use both terms. Are the two terms interchangeable? Is there a difference in meaning?

回答1:

The definitions and uses of these terms vary by Lisp dialect and community, so there is no clear answer to your question for Lisps in general.

For their use in Common Lisp, see Rainers detailed answer. To give a short summary:

The HyperSpec entry for form:

form n. 1. any object meant to be evaluated. 2. a symbol, a compound form, or a self-evaluating object. 3. (for an operator, as in <<operator>> form'') a compound form having that operator as its first element.A quote form is a constant form.''

The HyperSpec entry for expression:

expression n. 1. an object, often used to emphasize the use of the object to encode or represent information in a specialized format, such as program text. The second expression in a let form is a list of bindings.'' 2. the textual notation used to notate an object in a source file.The expression 'sample is equivalent to (quote sample).''

So, according to the HyperSpec, expression is used for the (textual) representation, while form is used for Lisp objects to be evaluated. But, as I said above, this is only the definition of those terms in the context of the HyperSpec (and thus Common Lisp).

In Scheme, however, the R5RS doesn't mention form at all, and talks about expressions only. The R6RS even gives a definition that almost sounds like the exact opposite of the above:

At the purely syntactical level, both are forms, and form is the general name for a syntactic part of a Scheme program.

(Talking about the difference between (define …) and (* …).)



回答2:

Summary

A form is Lisp code as data. An expression is data as text.

Explanation

In Common Lisp form and expression have two different meanings and it is useful to understand the difference.

A form is an actual data object inside a running Lisp system. The form is valid input for the Lisp evaluator.

EVAL takes a form as an argument.

The syntax is:

eval form => result*

EVAL does not get textual input in the form of Lisp expressions. It gets forms. Which is Lisp data: numbers, strings, symbols, programs as lists, ...

CL-USER 103 > (list '+ 1 2)
(+ 1 2)

Above constructs a Lisp form: here a list with the symbol + as the first element and the numbers 1 and 2 as the next elements. + names a function and the two numbers are the arguments. So it is a valid function call.

CL-USER 104 > (eval (list '+ 1 2))
3

Above gives the form to EVAL and computes a result. We can not see forms directly - we can let the Lisp system create printed representations for us.

The form is really a Lisp expression as a data object.

This is slightly unusual, since most programming languages are defined by describing textual input. Common Lisp describes data input to EVAL. Forms as data structures.

The following creates a Lisp form when evaluated:

"foo"         ; strings evaluate to themselves

'foo          ; that evaluates to a symbol, which then denotes a variable

123

(list '+ 1 2) ; evaluates to a list, which describes a function call

'(+ 1 2)      ; evaluates to a list, which describes a function call

Example use:

CL-USER 105 > (defparameter foo 42)
FOO

CL-USER 106 > (eval 'foo)
42

The following are not creating valid forms:

'(1 + 2)            ; Lisp expects prefix form

(list 1 '+ 2)       ; Lisp expects prefix form

'(defun foo 1 2)'   ; Lisp expects a parameter list as third element

Example:

CL-USER 107 > (eval '(1 + 2))

Error: Illegal argument in functor position: 1 in (1 + 2).

The expression is then usually used for a textual version of Lisp data object - which is not necessarily code. Expressions are read by the Lisp reader and created by the Lisp printer.

If you see Lisp data on your screen or a piece of paper, then it is an expression.

(1 + 2)             ; is a valid expression in a text, `READ` can read it.


回答3:

This is by no means a scientific or standards-based answer, but the distinction that I have built up in my own head based on things I've heard is more along the lines of: an expression is a form which will be (or can be) evaluated in the final program.

So for instance, consider the form (lambda (x) (+ x 1)). It is a list of three elements: the symbol lambda, the list (x), and the list (+ x 1). All of those elements are forms, but only the last is an expression, because it is "intended" for evaluation; the first two forms are shuffled around by the macroexpander but never evaluated. The outermost form (lambda (x) (+ x 1)) is itself an expression as well.

This seems to me to be an interesting distinction, but it does mean it is context-sensitive: (x) is always a form, and may or may not be an expression depending on context.