【问题标题】:Scheme recursion error方案递归错误
【发布时间】:2010-11-14 01:10:55
【问题描述】:

这个递归函数似乎工作正常,将我想要的确切字母 B 和 C 添加到结果列表中,然后当它完成时,它正确地看到已经到达最后一个元素。

然后它执行基本情况,并发生我无法解释的错误。是什么导致了这个错误?

    (define(preceding-R X Vector result)    
      (if (eq? '() (cdr (vector->list Vector)))
               result
              (helper X Vector result)))

(define (helper X Vector result)
   (if(eqv? X (cadr (vector->list Vector))) ((set! result (cons result (car (vector->list Vector)))) (preceding-R X (list->vector (cdr (vector->list Vector))) result))
                            (preceding-R X (list->vector (cdr (vector->list Vector))) result)))

(preceding-R 'a #(b a c a) '()))

错误:

程序应用程序:预期程序,给定:#;参数是: ((() . b) . c)

【问题讨论】:

  • 请格式化您的代码并简要说明代码必须做什么。

标签: scheme racket


【解决方案1】:

这里有一些不是“绝对可怕”的代码:

(define preceding-R 
  (lambda (x vec)
    (define helper
      (lambda (ls)
        (cond
          ((null? ls) '())
          ((null? (cdr ls)) '())
          ((eq? (cadr ls) x) (cons (car ls) (helper (cdr ls))))
          (else (helper (cdr ls))))))
    (helper (vector->list vec))))

> (preceding-R 'a #(b a c a))
(b c)

Eli Barzilay 说得有道理;如果我对原始代码进行评分,由于他指出的事情,我可能会奖励不到一半的分数:

  • 在大多数情况下应避免使用set!,并且通常不允许在涉及基本 Scheme 代码的作业问题上使用。不得不使用 set! 是一种常见的说法,即递归没有被很好地理解。
  • 由于begin“丢弃”除最后一个表达式之外的所有结果,这意味着非尾表达式具有副作用(如set!),因此begin通常不会出现在教育问题。
  • 一遍又一遍地来回转换显然是一种浪费。可以进行一次转换,但您可能一开始就可以使用列表而不是向量。列表是 Scheme 中最常用的数据结构,尤其是因为它们与递归配合得很好。
  • 您的代码将在第二行的空列表中出错:(preceding-R 'a #()) => Error: Attempt to apply cdr on '()
  • 如果您确实使用set! 修改结果,则没有理由传递结果。这是额外的行李。
  • Eli 最后一点是你可以写:

.

(define (helper X Vector result)
  (preceding-R X (list->vector (cdr (vector->list Vector)))
               (if (eq? X (cadr (vector->list Vector)))
                   (cons (car (vector->list Vector)) result)
                   result)))

保存一些重复的代码。

【讨论】:

    【解决方案2】:
    (define (preceding-R X Vector result)    
      (if (eq? '() (cdr (vector->list Vector)))
        result
        (helper X Vector result)))
    
    (define (helper X Vector result)
      (if (eqv? X (cadr (vector->list Vector)))
        (begin
          (set! result (cons (car (vector->list Vector)) result))
          (preceding-R X (list->vector (cdr (vector->list Vector))) result))
        (preceding-R X (list->vector (cdr (vector->list Vector))) result)))
    
    (preceding-R 'a #(b a c a) '())
    

    我添加了开始通话。如果你想要多个表达式,如果你不能只将它们包装在 () 中,它会被解释为对 void 的函数调用(由 set 返回!),参数由对前面的-R 的递归调用返回。

    【讨论】:

    • 非常感谢,我知道问题与此有关,但我尝试使用 cond 来解决该问题,因为我知道它默认使用 begin 。显然我没有正确实施它。再次感谢。
    • 这段代码太可怕了。它无缘无故地使用set!,它只是为此使用begin,它会在某些情况下抛出错误,它不断将向量转换为列表并返回向量,它在外部级别有if helper 当它可以很容易地推入最后一个参数时,等等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 2013-09-22
    • 1970-01-01
    相关资源
    最近更新 更多