... или каким-либо другим способом решения этой проблемы.
Я не понимаю, почему OP-код пытается использовать макросы для создания более высокого уровня порядок здесь. compose
Процедура, которая принимает один или несколько аргументов процедуры, может быть легко написана с использованием точечного синтаксиса для определений процедур.
(define (compose f . fs)
(if (null? fs)
(lambda (x) (f x))
(let ((g (apply compose fs)))
(lambda (x) (f (g x))))))
Здесь, когда предоставляется только один аргумент, процедура, которая применяет f
к один аргумент x
возвращается. В противном случае возвращается процедура, которая применяет f
к композиции оставшихся аргументов процедуры, а последний аргумент процедуры применяется к одному аргументу x
.
Вот демонстрация REPL:
> (define (double x) (* 2 x))
> (define (reciprocal x) (/ 1 x))
> (define (square x) (* x x))
> (define (add1 x) (+ x 1))
> (define doros (compose double reciprocal square))
> (define rodos (compose reciprocal double square))
> (doros 4)
1/8
> (rodos 4)
1/32
> (define dosoaor (compose double square add1 reciprocal))
> (define soroaod (compose square reciprocal add1 double))
> (= (dosoaor 4)
(double (square (add1 (reciprocal 4)))))
#t
> (dosoaor 4)
25/8
> (= (soroaod 4)
(square (reciprocal (add1 (double 4)))))
#t
> (soroaod 4)
1/81
Составленная процедура doros
должна сначала возвести в квадрат свой аргумент, затем взять обратную величину результата и, наконец, возвратить дважды этот результат. Таким образом, (doros 4)
должно быть равно (* 2 (/ 1 (* 4 4)))
==> 1/8
, как видно из вышеприведенной демонстрации REPL.
Аналогично, rodos
должен сначала возвести в квадрат свой аргумент, затем удвоить результат и, наконец, принять взаимность этого результата. Таким образом, (rodos 4)
должно быть равно (/ 1 (* 2 (* 4 4)))
==> 1/32
, что соответствует результату REPL.
Тесты, составляющие четыре процедуры, также успешны.