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
和explicite
lambda
使用也是一种选择:

(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))