【问题标题】:Issues with conditionals in SchemeScheme中的条件问题
【发布时间】:2013-11-12 01:28:46
【问题描述】:

我正在使用带有完整 Swindle 包的 Scheme,并且我正在尝试使用条件来递归地确定整数的偶数/奇数。我的代码如下:

(define (odd? x)(
            (cond 
              ((= x 0) '#f)
              ((= x 1) '#t)
              ((= (even? (- x 1)) #t) '#f)
              (else '#t))))

(define (even? x)(
              (cond
                ((= x 0) '#f)
                ((= x 2) '#t)
                ((= (odd? (- x 1)) #t) '#f)
                (else '#t))))

但是,当我运行 (even?x) 或 (odd?x) [x 是某个数字,没关系,因为我得到同样的错误] 我得到:应用程序:不是过程; 期望一个可以应用于参数的过程 给定:#t 参数...:[无]

有人可以帮忙吗?谢谢。我不是 100% 熟悉理想的 Scheme 语法,所以可能就是这样。

【问题讨论】:

  • 首先,您的 cond 语句之前有一个额外的括号。第二个 '=' 只比较数值。你已经期待了吗?返回一个真假。 3. 你为什么在奇数和偶数之间跳来跳去,你的筹码量或你的筹码一直这样增长。跳过第三种情况,让你的 else 跳转到 (even? (- x 2)) 的尾调用。 4. 负数呢?
  • @WorBlux 到您的 3.,在 Scheme 中,相互尾递归过程保证在恒定堆栈空间中运行。 OP的代码自然就变成了这样的形式。 -- 重点在于使用 Peano 算术。

标签: scheme


【解决方案1】:

cond 表达式周围有一对错误的括号(这是导致报告错误的原因)。但是,每个过程中的条件太多了,并且由于您使用= 将数字与布尔值进行比较,因此会出现违反合同的情况。为了解决这个问题,您可以在此处将 = 替换为 equal?

((equal? (even? (- x 1)) #t) '#f)

在这里:

((equal? (odd? (- x 1)) #t) '#f)

但是,程序仍然会给出错误的结果:

(even? 5)
=> #t
(odd? 7)
=> #f

老实说,我认为最好简化实现,这样可以解决所有问题。试试这个:

(define (odd? x)
  (cond ((= x 0) #f)
        (else (even? (- x 1)))))

(define (even? x)
  (cond ((= x 0) #t)
        (else (odd? (- x 1)))))

现在我们将得到正确答案:

(even? 4)
=> #t
(even? 5)
=> #f
(odd? 6)
=> #f
(odd? 7)
=> #t

【讨论】:

  • 您的第三个反对意见不正确。 OP 的 even?/odd? 仅使用 x,x-1,0,2,1 调用,并且仅返回 #t,#f
  • @WillNess 不正确。获取 OP 的代码,删除 cond 周围的额外 () 并运行 (even? 4)。您将收到 contract violation expected: number? given: #t 错误。
  • 啊哈!麻省理工学院计划更好(这里)! ;) ;) 它给了我 ";The object #t, passed as the first argument to integer-equal?, is not the correct type." 即使用= 比较布尔值是一个问题:尝试(= #f #t) 给我同样的错误。所以它是= 接收一个布尔值,而不是其中一个函数。 :)
  • @WillNess 明白了你的意思。我根据您的建议编辑了我的答案,谢谢!
  • @WillNess 但还要注意:只需将= 替换为equal?,OP 的代码仍然会失败:(even? 5) 返回#t
【解决方案2】:

括号中的任何 Scheme 表单都是 应用程序,例如 (sin 42)(42 sin)。第一个调用sin 作为带有参数42 的函数并产生一个值;第二个尝试使用参数sin 调用42,但42 不是过程,因此这会导致错误。同样(42) 是一个没有参数的应用程序;它仍然必须有一个程序作为它的第一部分应用,没有参数被调用,对吧?在 Scheme 中,括号很重要,它们不仅仅用于对内容进行分组(因为它们可能在某些其他语言中)。所以额外的括号会导致额外的尝试评估结果,这是一个布尔值,即不是一个过程,所以这是一个错误。

那么,'#f 就是#f#t 类似(他们都对自己进行评估);并且条件 (= test #t)1(equal? test #t)test 相同(产生相同的布尔结果集)((1 我们不能使用= 来比较布尔值,它应该只用于数字)))

(define (odd? x)
        (cond 
          ((= x 0) #f)
          ((= x 1) #t)
          ((even? (- x 1)) #f)
          (else #t)))

另外,(if test #f else...)(if (not test) else... #f) 相同:

(define (odd? x)
        (cond 
          ((= x 0) #f)
          ((= x 1) #t)
          ((not (even? (- x 1))) #t)
          (else #f)))                 ; (else ...) is like (#t ...)

使用逻辑连接词,可以合并具有相同结果的子句,并且可以重新排列互斥子句(通过显式保护可以实现互斥):

(define (odd? x)
        (cond 
          ((and (/= x 0)              ; a guard
                (or (= x 1) 
                    (not (even? (- x 1))))) #t)
          ((or (= x 0) #t) #f)))

(cond (test #t) (else #f)(if test #t #f) 只是test

(define (odd? x) (and (> x 0)         ; `>` is better
                      (or (= x 1) 
                          (not (even? (- x 1))))))

守卫(> x 0) 防止负xes 的失败。

但是,这是完全错误的n 是奇数,n-1 必须是偶数,而不是相反!

(define (odd? x) (and (> x 0)         ; work only for positive integers
                      (or (= x 1) 
                          (even? (- x 1)))))

我们可以写(not (odd? (- x 1))),但它不会是尾递归的。它tail recursive modulo consnot充当“构造函数”),但出于某种历史上的侥幸2,TRMC Scheme 实现不需要优化。 andor 表单中的最后一个表达式实际上是 in tail position。但不在not 中。 ((2 尽管是described as early as 1974.))

even? 的定义重复相同的操作。

【讨论】:

    猜你喜欢
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2011-02-19
    • 2021-08-19
    • 2018-09-29
    • 2020-06-06
    相关资源
    最近更新 更多