问题
So let's say I want to call some function. If I've defined the function with a defun, I just use the name of the function at the beginning of a list followed by it's arguments like so (I will be using "=>" in examples to show the output of entering the code into the CLisp REPL):
(defun f (a) (lambda (b) (+ a b))) => F
(f 12) => #<FUNCTION :LAMBDA (B) (+ A B)>
Simple enough. The first element of the list must be the name of a function, special operator, or macro. Except, the following is also valid:
((lambda (a) (+ a 12)) 1) => 13
A quick google-search reveals that LAMBDA is both a symbol and a macro. Trying to expand the macro yeilds:
(macroexpand '(lambda (a) (+ a 12))) => #'(LAMBDA (A) (+ A 12))
This is not helpful. I have no way to differentiate between the macro LAMBDA and the symbol LAMBDA, and I'm totally unclear as to why I can use a lambda expression as a function-name but not, say, #'f, which, to my knowledge, should evaluate to a valid function-designator for the function F in the same way that #'(LAMBDA (A) (+ A 12)) does and yet:
(#'f 12) => *** - EVAL: #'F is not a function name; try using a symbol instead
Is LAMBDA a special exception to the otherwise hard-set rule that the first element of an evaluated expression must be the name of some operation, or is there some more consistent ruleset that I'm misunderstanding?
回答1:
Lambda expressions and function names
A lambda expression is not a function name. function names in Common Lisp are defined to be either symbols or (setf symbol). A lambda expression is basically built-in syntax to describe an anonymous function.
Note that lambda expressions on their own are not meaningful in Common Lisp. They are only appearing in a lambda form (see below) and inside a form with the special operator function.
Lists as Forms
Is LAMBDA a special exception to the otherwise hard-set rule that the first element of an evaluated expression must be the name of some operation, or is there some more consistent ruleset that I'm misunderstanding?
The Common Lisp specification defines that there are only four list-based forms. A form is a valid Lisp piece of code.
- special forms (the form begins with a special operator)
- macro forms (the form begins with a macro operator)
- function forms (the form begins with a function operator)
- lambda forms (the form begins with a lambda expression)
See the Common Lisp HyperSpec: Conses as Forms.
Note that there is no mechanism in Common Lisp to extend this. There are only these four types of list-based forms. One could think of extensions: arrays as functions, CLOS objects as functions, different types of functions like fexprs, variables, ... None of those are supported by Common Lisp syntax for list-based forms and there is no portable mechanism to add those.
LAMBDA
LAMBDA has two different purposes in Common Lisp:
- it's the head of a lambda expression.
- as a macro
LAMBDA. This expands(lambda ....)into(function (lambda ....))
The macro LAMBDA was added to Common Lisp after the first language definition CLtL1 as a convenience to be able to write (lambda (x) x) instead of (function (lambda (x) x)) or #'(lambda (x) x). Thus it's an abbreviation for the function special operator form and makes code look a bit simpler and more Scheme-like.
回答2:
One can imagine the following translation happening to evaluate a function (ie the car does not name a macro or special operator) expression:
(foo arg1 arg2 ...)
~~~>
(funcall (function foo) arg1 arg2 ...)
And understand function as the special operator that translates the thing that goes in the first element of an expression into an actual function operator one can call. It is function which converts (mostly at compile time) a lambda expression into a closure that may be called.
Finally note that #'foo is shorthand for (function foo).
This is not how things actually work, in practice or in specification, as (function #'(setf foo)) is perfectly valid and may evaluate to a function of one exists, but ((setf foo) arg1 arg2 ...) cannot be a valid function call.
This does however explain why an expression like (#'f x) is invalid and the reason is that (function (function f)) is not a valid expression.
来源:https://stackoverflow.com/questions/54210225/why-is-a-common-lisp-lambda-expression-a-valid-function-name