计划程序冻结,没有例外

Rob*_*sen 0 scheme racket

好的,我正在大学上学这门课程,我们刚刚完成了第一次任务.我遇到了这个奇怪的事情.有时程序会冻结,绝对不做任何事情而不给我任何形式的警告,为什么这是......

采取以下程序:

(define (calc-week-day y1 m d w y2) ; anta y2 > y1
  (define (days-between-months m1 m2 y)
    (if (= m1 m2)
        0
        (+ (month-length y m1) (days-between-months (+ m1 1) m2 y))))
  (define (days-between-years y1 y2)
    (if (= y1 y2) 
        0
        (+ (year-length y1) (days-between-years (+ y1 1) y2))))
  (define (days-til-months-end d m y)
    (- (month-length y m) d))
  (define (calculate-day day offset)
    (cond ((> day 6) (calculate-day 0 (- offset 1)))
          ((= offset 0) day)
          (else (calculate-day (+ day 1) (- offset 1)))))

  (define dager-til-nyttår (+ (days-between-months m 12 y1)
                              (days-til-months-end d 12 y1) 1))
  (define dager-fra-nyttår (+ (days-between-months 1 m y2) d 2))
  (define dager-mellom-datoer (+ dager-til-nyttår (days-between-years y1 y2)
                                 dager-fra-nyttår))

  (num->day (calculate-day (day->num w) dager-mellom-datoer)))
Run Code Online (Sandbox Code Playgroud)

calc-week-dayy2 > y1总是花费两年时间.M =月,d =天,W =星期(星期一,星期二...)函数计算出相同的日期之间的天差y1y2,并计算出在一周中的一天y2...

此过程不能正常工作.这实际上不会产生任何输出.但是,如果我从中移除最后一个数字(2)(define dager-fra-nyttår ...)就可以正常工作并将一周中的某一天产生到输出屏幕(尽管不是正确的日期).

有谁知道这是为什么?(在Mac OSX Lion上使用Racket 5.2)

Gre*_*ott 5

听起来你陷入无限循环.

我的猜测是,无论是days-between-months或者days-between-years无休止地呼唤自己.

例如,days-between-months似乎假设m1<= m2.但是如果你用m1> 调用它m2,看起来它会继续"永远"自称 - 继续尝试增加m1直到它等于m2,但它永远不会,因为它已经更大了.(好吧,"永远",或者至少很长一段时间,直到整数值回绕.)

实际上,有两种方法可以解决这个问题.

  • "防御性编程"方式是将if测试从改变(= m1 m2)(<= m1 m2).很多程序员都会这样做.

  • 编写可靠的代码的方式是说,等一下,这个问题是通过废话值的函数调用者:该来电者应该是固定的,而不是功能默默地隐藏的错误.如果你喜欢这种方法,你可以用assertC语言添加一种语言,或者在这里你可以做一些(when (> m1 m2) (error))故意导致错误的事情.或者在Racket中,你可以使用a contract,如果你试图违反你所要求的条件,它会抱怨.

经过多年编写代码,我更喜欢第二种方法.但你会发现两种方式都有很好的论据.此外,它取决于您编码的系统的性质,您是否希望它对故障"脆弱",以便您可以找到并修复它们,或尽可能地混淆.还有一些人在"调试"版本中采用了脆弱的方法,对于发布的产品采用了宽容的方法.

最后,你的代码调用了几个函数,这些函数没有在你提供的内容中定义(比如month-lengthyear-length),而问题可能在那里,而不是我提到的内容.