Why sharp quote lambda expressions?

前端 未结 4 648
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-07 06:32

It is a technique used frequently in On Lisp, which is on Common Lisp:

> (mapcar #\'(lambda (x) (+ x 10))
         \'(1 2 3))
(11 12 13)
4条回答
  •  太阳男子
    2021-02-07 07:17

    Common Lisp assumed.

    Why is sharp-quote needed or even possible?

    If you want to compute a function object from a function name (especially if you want to refer to a lexical binding) or a lambda expression, you need the special operator FUNCTION, or shorter #'.

    lambda expressions return function objects,

    They don't. Lambda expressions can't even be evaluated.

    In Common Lisp it looks like (lambda () nil) can be evaluated. But it can't.

    Sometime after CLtL1 a macro LAMBDA has been added that expands it into a (FUNCTION ...) expression. This macro saves some typing and let's code look a bit more like Scheme. Let's check this LAMBDA macro:

    CL-USER 17 > (macroexpand-1 '(lambda () ()))  ; not a lambda expression
    (FUNCTION 
      (LAMBDA NIL NIL)                            ; <- this is a lambda expression
    )
    T
    

    This means that the following happens if you evaluate (lambda () ()):

    • LAMBDA is a macro. Thus the form gets expanded to (function (lambda () ())).
    • (function (lambda () ())) -> FUNCTION is a special operator. It returns a function object
    • ->

    If you write: #'(lambda () ()) or (function (lambda () ())), then you'll skip the macro expansion.

    Okay, now for something strange:

    CL-USER 18 > (lambda () ())   ; <- this is not a lambda expression.
                                  ;    it's a macro form, see above 
    #
    

    Because above is a macro form, it will be expanded first and then it can be evaluated.

    CL-USER 19 > (function          ; <- this is a special form
                  (lambda () ())    ; <- this is a lambda expression
                  )
    #
    

    Here it really is a lambda expression. Inside the special operator FUNCTION the form will not be macro expanded or similar.

    CL-USER 20 > (                  ; <- this is a function call
                  (lambda () ())    ; <- this is a lambda expression
                  )
    

    Above again, shows a lambda expression. Where ((function (lambda () ()))) is not valid Common Lisp. In the function position of a function call, Common Lisp expects either a function name or a lambda expression, but not something which needs to be evaluated.

    and sharp quoting returns function objects from names.

    FUNCTION, for which #' is a short notation, returns function objects from function names or lambda expressions.

    See the documentation: FUNCTION.

    I also have heard contradictory information on whether lambda expressions are names - in particular On Lisp contradicts the standard, but his code seems to work which also contradicts the standard.

    If you want to hear the last word, read the ANSI CL standard. Alternatively use the Common Lisp Hyperspec, which is web-readable and derived from the standard.

    On Lisp is definitely useful to read, but it might not follow the wording or semantics of ANSI CL in full detail. On Lisp was published after CLtL2, but before ANSI CL.

    What does it mean practically when writing code?

    If you are old, like me, and CLtL1 was the last thing you read of Common Lisp then write code like:

    (mapcar #'(lambda (x) (* x x)) '(1 2 3))
    

    If you are even older and grew up with Scheme, or are younger and have read the Common Lisp Hyperspec, then you might want to write:

    (mapcar (lambda (x) (* x x)) '(1 2 3))
    

    But for all, when it comes to function names, this is the default to write:

    (mapcar #'sin '(1 2 3))
    

提交回复
热议问题