好的,我正在大学上学这门课程,我们刚刚完成了第一次任务。我遇到了这个奇怪的事情。有时程序会冻结,绝对不做任何事情而不给我任何形式的警告,为什么这是......
采取以下程序:
(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)))
calc-week-day
基本上需要两年时间才能y2 > y1
。 m =月,d =天和w =星期几(星期一,星期二......)该函数计算出y1
和y2
中相同日期之间的天数差异,并计算出来y2
...
此过程无法正常工作。这实际上不会产生任何输出。但是,如果我从(define dager-fra-nyttår ...)
删除最后一位数字(2),它就可以正常运行,并在输出屏幕上生成星期几(虽然不是正确的日期)。
任何人都知道这是为什么? (在Mac OSX Lion上使用Racket 5.2)
答案 0 :(得分:5)
听起来你陷入无限循环。
我的猜测是,days-between-months
或days-between-years
无休止地呼唤着自己。
例如,days-between-months
似乎假定m1
< = m2
。但是如果你用m1
>来称呼它m2
,看起来它会继续“永远”自称 - 继续尝试增加m1
直到它等于m2
,但它永远不会,因为它已经更大了。 (好吧,“永远”,或者至少很长一段时间,直到整数值回绕。)
实际上,有两种方法可以解决这个问题。
“防御性编程”方式是将if
测试从(= m1 m2)
更改为(<= m1 m2)
。很多程序员都会这样做。
编写固体代码的方式就是说,等等,问题在于调用者将无意义的值传递给函数:调用者应该被修复而不是隐藏错误的功能。如果您喜欢这种方法,则可以使用C语言添加assert
,或者在此处执行类似(when (> m1 m2) (error))
的操作以故意导致错误。或者在Racket中,您可以使用contract
,如果您尝试违反所需条件,它会抱怨。
经过多年编写代码,我更喜欢第二种方法。但你会发现两种方式都有很好的论据。此外,它取决于您编码的系统的性质,您是否希望它对故障“脆弱”,以便您可以找到并修复它们,或尽可能地混淆。还有一些人在“调试”版本中采用了脆弱的方法,对于发布的产品采用了宽容的方法。
最后,您的代码会调用一些未在您提供的内容中定义的函数(例如month-length
和year-length
),而问题可能代替或除了我提到的。