2012-01-26 4 views
0

Хорошо, я беру этот класс схемы в университете, и мы только получили наше первое задание. Однако я переживаю эту странную вещь. Иногда программа будет замерзать, абсолютно ничего не делать, не дав мне какой-либо предупреждения, почему это ...Программа программы зависает без исключений

Возьмем следующую процедуру:

(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. ..

Эта процедура не работает должным образом. На самом деле это не приведет к выходу. Однако, если я удаляю последнюю цифру (2) с (define dager-fra-nyttår ...), она отлично работает и выдает день недели на экран вывода (хотя и не правильные даты).

Кто-нибудь знает, почему это так? (с использованием Racket 5.2 на Mac OSX Lion)

+1

У вас есть тестовые примеры для любой из ваших вспомогательных функций? Вы знаете, работает ли какая-либо из ваших вспомогательных функций? Это не так легкомысленный вопрос, как может показаться на первый взгляд. Я не уверен, что расчетный день заканчивается при всех ожидаемых условиях. Например, если вы передадите ему день больше 6 и смещение, равное нулю, оно не прекратится. Кстати, если вы используете DrRacket, попробуйте нажать кнопку «Стоп». Он должен сказать вам, где ваша программа была компьютерной. Можете дать нам подсказку о том, где происходит бесконечный цикл. – dyoo

+0

Помощник был написан профессионалом и использовался как минимум на пару лет, поэтому я предполагаю, что они работают как рекламируемые, даже если нет тестовых случаев ... –

+0

«Вспомогательные функции», я имею в виду все внутренне определенные функции в calc-week-day. Предположительно, ваш профессор не писал их, или что еще вам нужно делать? :) Кроме того, когда вы просите помощи в отслеживании того, что выглядит как бесконечный цикл, укажите пример ввода, чтобы люди, которые хотят помочь, могли реплицировать ваш сценарий. Какие входы вы передаете в calc-week-day, и если программа работает правильно, что вы ожидаете увидеть? – dyoo

ответ

5

Похоже, вы застряли в бесконечном цикле.

Я предполагаю, что либо days-between-months, либо days-between-years вызывает себя бесконечно.

Например, days-between-months, по-видимому, предполагает, что m1 < = m2. Но если вы назовете его m1>, похоже, он будет продолжать называть себя «навсегда» - продолжайте пытаться увеличивать m1 до тех пор, пока он не будет равен m2, но он никогда не будет, потому что он уже больше. (Ну, «никогда» или, по крайней мере, в течение длительного времени, пока целое значение не обернется вокруг.)

Практически существует два способа решения этой проблемы.

  • «защитное программирование» способ изменить if тест с (= m1 m2) до (<= m1 m2). Много программистов сделают это.

  • Дать Solid Кодекс путь будет сказать, подождите, проблема с вызывающей проходящей значения нонсенс функции: The вызывающему должен быть фиксированным, а не функции молча скрывающей ошибку. Если вам нравится этот подход, вы должны добавить assert на языке, таком как C, или здесь вы можете сделать что-то вроде (when (> m1 m2) (error)), чтобы умышленно вызвать ошибку. Или в Racket вы можете использовать contract, и он будет жаловаться, если вы попытаетесь нарушить условия, которые вам нужны.

После многих лет написания кода, я предпочитаю второй подход. Но вы найдете хорошие аргументы в обоих направлениях. Кроме того, это зависит от характера системы, которую вы кодируете, хотите ли вы, чтобы она была «хрупкой» в случае сбоев, чтобы вы могли найти и исправить их, или путаться, насколько это возможно. Также некоторые люди используют хрупкий подход в «отладочных» сборках и толерантный для выпущенного продукта.

И, наконец, ваш код вызывает пару функций, которые не определены в том, что вы предоставили (например, month-length и year-length), и проблемы могут возникнуть вместо или в дополнение к тому, что я упомянул.

+0

Хмм, звучит правдоподобно. Чтение этого кода не так просто, как чтение Javascipt или Java, как я тоже использую, что может быть поэтому я не заметил это сам ... Я проверю это, когда вернусь с работы и посмотрю, если это ответ Я ищу. Тем временем я дам вам проголосовать за отличный ответ =) –

+1

Чтение будет легче, как только ваш мозг перемодет себя. Вскоре вы сможете переключаться между чтением языков '{}' и языков '()' - так же легко, как перелистывание между чтением на английском и норвежском языках. :) –

Смежные вопросы