Compose example in Paul Graham's ANSI Common Lisp

前端 未结 3 1817
迷失自我
迷失自我 2020-12-31 08:28

Can anybody explain an example in Paul Graham\'s ANSI Common Lisp page 110?

The example try to explain the use &rest and lambda to create functional programming

3条回答
  •  南方客
    南方客 (楼主)
    2020-12-31 08:53

    destructuring-bind combines destructors with binding. A destructor is a function that lets you access a part of a data structure. car and cdr are simple destructors to extract the head and tail of a list. getf is a general destructor framework. Binding is most commonly performed by let. In this example, fns is (#'list #'round #'sqrt) (the arguments to compose), so (reverse fns) is (#'sqrt #'round #'list). Then

    (destructuring-bind (fn1 . rest) '(#'sqrt #'round #'list)
      ...)
    

    is equivalent to

    (let ((tmp '(#'sqrt #'round #'list)))
      (let ((fn1 (car tmp))
            (rest (cdr tmp)))
        ...))
    

    except that it doesn't bind tmp, of course. The idea of destructuring-bind is that it's a pattern matching construct: its first argument is a pattern that the data must match, and symbols in the pattern are bound to the corresponding pieces of the data.

    So now fn1 is #'sqrt and rest is (#'round #'list). The compose function returns a function: (lambda (&rest args) ...). Now consider what happens when you apply that function to some argument such as 4. The lambda can be applied, yielding

    (reduce #'(lambda (v f) (funcall f v))
                '(#'round #'list)
                :initial-value (apply #'sqrt 4)))
    

    The apply function applies fn1 to the argument; since this argument is not a list, this is just (#'sqrt 4) which is 2. In other words, we have

    (reduce #'(lambda (v f) (funcall f v))
                '(#'round #'list)
                :initial-value 2)
    

    Now the reduce function does its job, which is to apply #'(lambda (v f) (funcall f v)) successively to the #'round and to #'list, starting with 2. This is equivalent to

    (funcall #'list (funcall #'round 2))
    → (#'list (#'round 2))
    → '(2)
    

提交回复
热议问题