return 组合函数的方案函数
Scheme function that return composition of functions
如何实现一个函数,将任意数量的一个参数的过程作为输入,returns另一个函数是这些过程在Scheme中的组合。
例如:
(define (f x) (* x 2))
(define (g x) (* x 3))
(define (h x) (- x))
((comp-func f g h) 1) => -6
((comp-func f g) 1) => 6
((comp-func h) 1) => -1
((comp-func) 1) => 1
一个干净的解决方案是
(define (comp-func . procs)
(define (comp-rec arg procs)
(if (null? procs)
arg
((car procs) (comp-rec arg (cdr procs)))))
comp-rec)
然而,对于此解决方案,您需要这样称呼它 ((comp-func f g h) 1 (list f g h))
。
如果您像在示例中那样调用它,这是一个可行的解决方案,但是它有点丑陋,因为我们需要使用 set!
来更改 procs
参数。
(define (comp-func . procs)
(define (comp-rec arg)
(if (null? procs)
arg
(let ((proc (car procs))
(rest (cdr procs)))
(set! procs rest)
(proc (comp-rec arg)))))
comp-rec)
正如所写,这个问题是模棱两可的,因为我们无法判断您在编写函数时的顺序。也就是说,我们无法判断是否
((comp-func f g h) 1) 计算 (f (g (h 1))) 或 (h (g (f 1))),因为在这种情况下两者都会计算出 -6。也就是说,这个问题可以通过 fold 或 reduction 来解决;一旦您知道如何组合 两个 函数,您就可以在函数列表上减少该函数。首先,组合两个函数很简单:
(define (compose2 f g)
;; Returns a function that computes (g (f x)).
(lambda (x)
(g (f x))))
现在,将函数 f 折叠到具有初始值 i 的列表 (x1 x2 ... xn) 意味着计算
(f ... (f (f (f i x1) x2) x3 ...) xn)
组合函数列表 (f1 f2 f3 f4) 只是 折叠 compose2 函数,初始值为恒等式功能。
(define (identity x)
x)
(define (compose . functions)
(reduce compose2 identity functions))
我将在顺序重要的地方使用一些函数,以便我们可以看到结果的差异:
(define (f x) (* x x))
(define (g x) (+ x 3))
(display ((compose f g) 3))
;=> 12 == (g (f 3)) == (3^2)+3
(display ((compose g f) 3))
;=> 36 == (f (g 3)) == (3+3)^2
如何实现一个函数,将任意数量的一个参数的过程作为输入,returns另一个函数是这些过程在Scheme中的组合。
例如:
(define (f x) (* x 2))
(define (g x) (* x 3))
(define (h x) (- x))
((comp-func f g h) 1) => -6
((comp-func f g) 1) => 6
((comp-func h) 1) => -1
((comp-func) 1) => 1
一个干净的解决方案是
(define (comp-func . procs)
(define (comp-rec arg procs)
(if (null? procs)
arg
((car procs) (comp-rec arg (cdr procs)))))
comp-rec)
然而,对于此解决方案,您需要这样称呼它 ((comp-func f g h) 1 (list f g h))
。
如果您像在示例中那样调用它,这是一个可行的解决方案,但是它有点丑陋,因为我们需要使用 set!
来更改 procs
参数。
(define (comp-func . procs)
(define (comp-rec arg)
(if (null? procs)
arg
(let ((proc (car procs))
(rest (cdr procs)))
(set! procs rest)
(proc (comp-rec arg)))))
comp-rec)
正如所写,这个问题是模棱两可的,因为我们无法判断您在编写函数时的顺序。也就是说,我们无法判断是否 ((comp-func f g h) 1) 计算 (f (g (h 1))) 或 (h (g (f 1))),因为在这种情况下两者都会计算出 -6。也就是说,这个问题可以通过 fold 或 reduction 来解决;一旦您知道如何组合 两个 函数,您就可以在函数列表上减少该函数。首先,组合两个函数很简单:
(define (compose2 f g)
;; Returns a function that computes (g (f x)).
(lambda (x)
(g (f x))))
现在,将函数 f 折叠到具有初始值 i 的列表 (x1 x2 ... xn) 意味着计算
(f ... (f (f (f i x1) x2) x3 ...) xn)
组合函数列表 (f1 f2 f3 f4) 只是 折叠 compose2 函数,初始值为恒等式功能。
(define (identity x)
x)
(define (compose . functions)
(reduce compose2 identity functions))
我将在顺序重要的地方使用一些函数,以便我们可以看到结果的差异:
(define (f x) (* x x))
(define (g x) (+ x 3))
(display ((compose f g) 3))
;=> 12 == (g (f 3)) == (3^2)+3
(display ((compose g f) 3))
;=> 36 == (f (g 3)) == (3+3)^2