(composition) in Common Lisp

We find that this function constructor implements composition in P. Graham "ANSI Common Lisp" (p. 110). The arguments are n> 0 quoted function names. I do not understand it completely, so I will give the code here and ask the following questions:

(defun compose (&rest fns) (destructuring-bind (fn1 . rest) (reverse fns) #'(lambda (&rest args) (reduce #'(lambda (vf) (funcall fv)) rest :initial-value (apply fn1 args))))) 

The list of arguments for the layout is canceled and unpacked, its (now the first) element is bound to "fn1", and the rest is "rest". The body of the outermost lambda is the abbreviation: (funcall fi (funcall fi-1 ...)), with operands in inverted order to restore the original one.

1) What is the role of the external lambda expression? Namely, where does he get his โ€œargumentsโ€ from? Is the data structure specified as the first argument to destructuring-bind? 2) Where the innermost lambda takes two of its arguments:

I mean, I can appreciate what the code does, but still the lexical domain is a bit of a mystery to me. Looking forward to any comments! Thanks in advance, // Marco

+6
source share
2 answers

This is probably easier if you look at a few practical examples first:

 (defun compose1 (a) (lambda (&rest args) (apply a args))) (defun compose2 (ab) (lambda (&rest args) (funcall a (apply b args)))) (defun compose3 (abc) (lambda (&rest args) (funcall a (funcall b (apply c args))))) 

Thus, the external lambda is the return value: a function that takes any arguments, what it does with it, applies the last function and associates all the others in the reverse order with the result obtained from the last function.

Note: compose1 could be more simply defined as (defun compose1 (a) a) .

A somewhat equivalent but less effective version may be

 (defun compose (&rest functions) (if (= (length functions) 1) (car functions) (lambda (&rest args) (funcall (first functions) (apply (apply #'compose (rest functions)) args))))) 
+10
source

1) The outer lambda creates a closure for you, because the result (union ...) is a function that calibrates the composition of other functions.

2) The innermost lambda receives the ists argument from the reduce function. The abbreviation takes a function (the innermost lambda) of two arguments and applies it stepwise to the list, for example.

  (reduce #'- '(1 2 3 4)) is (- (- (- 1 2) 3) 4) 
+2
source

Source: https://habr.com/ru/post/956159/


All Articles