For loop 错误:对于:未定义(方案)

For loop 错误:对于:未定义(方案),for-loop,scheme,For Loop,Scheme,我必须在Scheme(R5RS)中创建一个函数,其工作原理如下: (电源接近b n) 它必须返回一个我称之为“e”的整数,即: b^e>n 用b,e和n个整数 因此,如果我们这样做: (电源接近210) 它必须返回4,因为4是b^e>n的第一个整数 我已经用迭代的方式做了这个函数,但是我必须用递归的形式。 这是我的代码: (define e 0) (define (power-close-to b n) (for ((e (< (expt b e) n)) (+ e 1))

我必须在Scheme(R5RS)中创建一个函数,其工作原理如下: (电源接近b n) 它必须返回一个我称之为“e”的整数,即: b^e>n 用b,e和n个整数

因此,如果我们这样做: (电源接近210) 它必须返回4,因为4是b^e>n的第一个整数 我已经用迭代的方式做了这个函数,但是我必须用递归的形式。 这是我的代码:

(define e 0)
(define (power-close-to b n)
  (for ((e (< (expt b e) n))
    (+ e 1))
    e))
(定义e 0)
(定义(功率接近b n)
(对于((e(<(expt b e)n))
(+e 1))
e) )
但当我尝试它时,Scheme给出了以下错误:“for:undefined 因此,我的方案似乎不知道“for”的程序,但我在互联网上的多个方案代码中看到了它,所以我不明白为什么在我的情况下,他说他不知道“for”

谢谢你的帮助

编辑:我试着让它递归,我就是这样做的,但我认为它仍然是迭代的,我真的不知道如何让它递归

(define e 0)
(define (power-close-to b n)
  (if (< (expt b e) n)
    (and (set! e (+ e 1)) (power-close-to b n)) 
    e))
(定义e 0)
(定义(功率接近b n)
(如果(<(出口b e)n)
(和(设置为e(+e 1))(功率接近b n))
e) )
我也尝试过这个,但当我尝试它时,它从不打印任何内容,也永远不会结束(但这是递归的(我认为))

(定义e 0)
(定义(功率接近b n)
(如果(<(出口b e)n)
(*b(电源接近b n))
e) )

当有人要求您将Scheme中的递归过程转换为迭代过程时,通常意味着您必须使用尾部递归,而不是使用该语言的循环结构

请注意,并非所有的Scheme解释器都提供
for
循环(大多数解释器将提供
do
循环,但我认为这不是练习的重点)。您报告的错误意味着您的解释器没有用于构造的
,因此您很可能需要以尾部递归方式重写过程。我给你举一个例子来说明我的意思,这是一个递归阶乘:

(define (fac n)
  (if (zero? n)
      1
      (* n (fac (sub1 n)))))

(fac 10)
=> 3628800
现在,同样的过程可以这样编写,即生成一个迭代过程(即使在语法上,它仍然使用递归):

你问,这有什么意义?第二个版本的过程是以尾部递归形式编写的(请注意,在递归调用结束后,没有什么可以做的),因此一个名为kicks的编译器技巧将在常量堆栈空间中运行该过程,就像其他非函数式语言中的循环一样高效——这使得递归调用非常便宜。现在,试着把你的
能力写得接近
实现,这样它就使用了一个尾部调用。

与传统循环最接近(最方便)的是命名let(搜索“命名let”)。看起来是这样的:

(define (power-close-to b n)
  (let loop ((e 0))
    (if (<= (expt b e) n)
        (loop (+ e 1))
        e)))

(display (power-close-to 2 10))

谢谢你的回答,在这种情况下,我已经做的函数是迭代形式的。所以现在我试着让它递归,但我有一个问题。当使其递归时,就像我在互联网上和你的例子中看到的那样,最后我必须做一些事情,比如+,-,*,/但在我的例子中,我不能这样做,因为我必须用1加密“e”,但e不是我函数的参数。那么,我怎样才能使它递归呢?@HyperZ开始将
e
作为参数传递,将该值保留为全局变量是一个非常糟糕的主意,这不是方法。不要使用
set
,只要您一直将其作为参数传递并作为参数更新它,就没有必要对值进行变异,就像我在示例中对
acc
所做的那样是的,但是我必须对我的函数执行其中一项(+、-、*、/),就像在u'r示例中所做的那样:(*n(fac(sub1 n)))))但我的问题是,我不必对我的函数做这4件事中的任何一件,我只需要把“e”加上1,它必须是一个递归形式。这就是为什么我不明白怎么做:(我也可能不会引入第三个参数。@HyperZ要在不使用
+
的情况下增加
e
,请使用
add1
过程。引入第三个参数是最干净的方法,如果你不能做到,因为你的老师禁止,那么,这太糟糕了-这将导致一个不优雅的答案;但是还有其他选择:你可以使用一个内部帮助程序,或者一个命名的
let
,这样外部函数就不必接收额外的参数。使用我在上面向您展示的内容,我相信您可以编写解决方案,现在由您决定。“大多数应该提供一个do循环”,是不是
do
R5RS?我没有遇到过没有它的方案?您混淆了什么“迭代”和“递归”"意思是。在Scheme中,编写递归解决方案是很常见的,但其中一些递归解决方案在编写为尾部递归时表现为迭代。问题中的第一个实现不起作用,
for
在您的解释器中不存在。您使用的是什么Scheme实现?您给了我两种迭代形式,我还有iterative形式。但我必须生成一个递归形式。@OscarLopez我尝试使用let,但它也是迭代的,因为我执行(+e 1),然后再次调用我的函数。@HyperZ循环正在调用自己,这是递归的。
(define (fac n acc) ; now the result is stored in the accumulator parameter
  (if (zero? n)     ; when recursion ends
      acc           ; return accumulator
      (fac (sub1 n) (* n acc)))) ; else update accumulator in each iteration

(fac 10 1) ; initialize the accumulator in the right value
=> 3628800
(define (power-close-to b n)
  (let loop ((e 0))
    (if (<= (expt b e) n)
        (loop (+ e 1))
        e)))

(display (power-close-to 2 10))
(define (power-close-to b n)

  (define (loop e)
    (if (<= (expt b e) n)
        (loop (+ e 1))
        e))

  (loop 0))
(define (power-close-to b n e)
  (if (<= (expt b e) n)
      (power-close-to b n (+ e 1))
      e))
(power-close-to 2 10 0)