Scheme 使用尾部递归实现重复的函数组合
我需要定义一个函数Scheme 使用尾部递归实现重复的函数组合,scheme,racket,repeat,tail-recursion,function-composition,Scheme,Racket,Repeat,Tail Recursion,Function Composition,我需要定义一个函数(重复write n f),以便 ((重复写入n f)x)计算为(f(f(…(f x)…)) 其中存在函数f的n应用程序 例如: ((repeat-write 4 cdr) ’(1 2 3 4 5 6)) 评估为 ’(5 6) 我不太确定如何开始这项工作。要开始这项工作,我们可以尝试定义 (define ((repeat-compose 4 f) x) (f (f (f (f x))))) 而且 (define ((repeat-compose 3 f) x)
(重复write n f)
,以便
((重复写入n f)x)
计算为(f(f(…(f x)…))
其中存在函数f
的n
应用程序
例如:
((repeat-write 4 cdr) ’(1 2 3 4 5 6))
评估为
’(5 6)
我不太确定如何开始这项工作。要开始这项工作,我们可以尝试定义
(define ((repeat-compose 4 f) x)
(f (f (f (f x)))))
而且
(define ((repeat-compose 3 f) x)
(f (f (f x))))
及
及
及
但这不是一个有效的骗局。首先,我们不能在Racket中同时有几个定义,即使是相互排斥的。我们需要把它写成一个条件
(define ((repeat-compose n f) x)
(cond
((= n 4) (f (f (f (f x)))) )
((= n 3) (f (f (f x))) )
((= n 2) (f (f x)) )
((= n 1) (f x) )
((<= n 0) x ))) ;; let's use `<=` here
但这也和
(define ((repeat-compose n f) x)
(cond
((= n 4) (f ((repeat-compose (- n 1) f) x)) )
((= n 3) (f ((repeat-compose (- n 1) f) x)) )
((= n 2) (f ((repeat-compose (- n 1) f) x)) )
((= n 1) (f ((repeat-compose (- n 1) f) x)) )
((<= n 0) x )))
也许能奏效。或者,您可能必须定义一个带有不需要的应用程序的助手内部函数,使其更明显地尾部递归。不使用compose
重复编写的尾部递归解决方案
我们定义一个尾部递归局部帮助函数%repeat compose
,并在其调用周围放置一个lambda
,以返回一个curryfied函数
(define (repeat-compose n f)
(define (%repeat-compose n f (acc nil))
(cond ((<= n 0) acc)
(else (%repeat-compose (- n 1) f (f acc)))))
(lambda (x)
(%repeat-compose n f x)))
它还通过如下定义工作:
(define ((repeat-compose n f) x)
(define (%repeat-compose n f (acc nil))
(cond ((<= n 0) acc)
(else (%repeat-compose (- n 1) f (f acc)))))
(%repeat-compose n f x))
使用compose
使用apply
和compose
(define (repeat-compose n f)
(apply compose (make-list n f)))
apply
需要函数和参数列表。
(生成列表n el)
通过重复元素n次来创建列表
(重复撰写5 f)
执行(应用撰写(列表f))
,这相当于(撰写f)
返回对给定参数执行5次的函数
((repeat-compose 5 cdr) '(1 2 3 4 5 6 7))
;; '(6 7)
使用compose
和explicitelambda
使用也是一种选择:
(define ((repeat-compose n f) x)
(for/fold ([acc x]) ([i (in-range n)]) (f acc)))
使用它:
> ((repeat-compose 4 cdr) (list 1 2 3 4 5 6))
(list 5 6)
该功能正是针对这种情况:
(require relation)
((power cdr 4) '(1 2 3 4 5 6))
=>”(56)
power
适用于任何类型和组合操作,而不仅仅是功能组合
[披露:我是这个实用程序的作者]明白了。。这确实满足了这个例子,但我想知道如何在这个例子中使用尾部递归。它不是尾部递归,但它是递归的,它是正确的,这是最重要的。这让你开始了。太好了,谢谢你的帮助!我将尝试并在此基础上构建..当我尝试运行最终代码时,会出现以下错误,我如何克服这些错误?````定义:需要函数名,但找到了一部分“```对于具有新代码的新问题,请在新的单独帖子中发布新问题,包括所有相关信息和代码,可能带有指向此帖子的链接以供背景参考。请编辑您的答案以使用
列表(列表f)
而不是”
这句话把每一个f
都变成了一个符号而不是一个函数(多么狂野、充满活力的回答啊!)实际上回答了问题。当n
较大时,它是否利用重复平方的幂运算来创建构造函数的更紧凑表示形式?@WillNess不知道这种优化,但它非常出色。它目前没有这样做,但我肯定有兴趣添加这一点。是的,当我阅读你的答案时,我的脑海中突然出现了这个想法。:)事实上,这是在写作的背景下。谢谢分享:)
(define ((repeat-compose n f) x)
(define (%repeat-compose n f (acc nil))
(cond ((<= n 0) acc)
(else (%repeat-compose (- n 1) f (f acc)))))
(%repeat-compose n f x))
(define (compose . functions)
(define (%compose functions acc)
(cond ((empty? functions) acc)
(else (%compose (cdr functions) ((car functions) acc)))))
(lambda (x)
(%compose functions x)))
;; or:
(define ((compose . functions) x)
(define (%compose functions acc)
(cond ((empty? functions) acc)
(else (%compose (cdr functions) ((car functions) acc)))))
(%compose functions x))
((compose cdr cdr cdr car) '(a b c d e f))
;; 'd ;; works!
(define (repeat-compose n f)
(apply compose (make-list n f)))
((repeat-compose 5 cdr) '(1 2 3 4 5 6 7))
;; '(6 7)
(define (repeat-compose n f)
(lambda (x) ((apply compose (make-list n f)) x)))
((repeat-compose 3 cdr) '(1 2 3 4 5))
;; '(4 5)
(define ((repeat-compose n f) x)
(for/fold ([acc x]) ([i (in-range n)]) (f acc)))
> ((repeat-compose 4 cdr) (list 1 2 3 4 5 6))
(list 5 6)
(require relation)
((power cdr 4) '(1 2 3 4 5 6))