Удалить лишнее else из оператора cond?

Я сейчас читаю 4-е издание "Маленького интригана". Одним из первых упражнений является создание функции insertR, которая вставляет значение справа от заданного значения в списке. В итоге книга приходит к следующему определению:

(define insertR
  (lambda (new old lat)
    (cond
      ((null? lat) (quote ()))
      (else (cond
              ((eq? (car lat) old)
               (cons old
                     (cons new (cdr lat))))
              (else (cons (car lat)
                          (insertR new old
                                   (cdr lat)))))))))

Мое собственное определение выглядело так:

(define insertR
  (lambda (new old lat)
    (cond
      ((null? lat) (quote ()))
      ((eq? (car lat) old) (cons old (cons new (cdr lat))))
      (else (cons (car lat) (insertR new old (cdr lat)))))))

Они эквивалентны?


person Andreas Brinck    schedule 23.09.2012    source источник
comment
Я считаю, что никто никогда не будет искать ваш заголовок (Являются ли следующие функции эквивалентными) в одной из поисковых систем... Не могли бы вы улучшить его?   -  person gdoron is supporting Monica    schedule 23.09.2012
comment
Да, я думаю, ты прав. Я изменил его на что-то, надеюсь, лучше, но не стесняйтесь менять его.   -  person Andreas Brinck    schedule 24.09.2012
comment
Каким-то образом подсказка от gdoron дала свои плоды: я сейчас читаю «Маленького интригана» и искал кого-то, кто заметил то же самое :) Однако, как кто-то еще сказал, на странице 41 авторы, похоже, поощряют такого рода упрощение.   -  person Alberto Moriconi    schedule 24.11.2012


Ответы (4)


Они есть, да, хотя я нахожу ваши более легкими для чтения. cond поддерживает несколько предложений и оценивает каждое из них до тех пор, пока одно из них не будет иметь значение true. Таким образом, следующее:

(else (cond
        ((eq? (car lat) old) (cons old (cons new (cdr lat))))
        (else (cons (car lat) (insertR new old (cdr lat)))))))))

Эквивалентно перемещению первого предложения второго cond в первое:

(cond
  ((null? lat) (quote ()))
  ((eq? (car lat) old) (cons old (cons new (cdr lat))))
  (else (cons (car lat) (insertR new old (cdr lat)))))))

Возможно, авторы книги сочли более ясным отделить терминальное состояние null от двух других, но если бы это было так, то вместо cond было бы достаточно if.

person João Silva    schedule 23.09.2012

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

person Óscar López    schedule 23.09.2012
comment
На самом деле пример, о котором я говорю, находится на странице 47, после того, как они показали, как сделать некоторые упрощения. Я все ждал, что они упростят и этот пример, но так и не сделали. - person Andreas Brinck; 24.09.2012

Да, два определения имеют одинаковое поведение.

Причина, по которой в книге две cond, заключается в том, что они служат двум разным целям. Внешний cond различает два случая типа данных list (список — это либо null, либо cons, вторым аргументом которого является список). Внешний cond определяется типом потребляемых данных; все структурно-рекурсивные функции в списках будут иметь этот внешний cond. Внутренний cond специфичен для конкретной определяемой функции.

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

person Ryan Culpepper    schedule 24.09.2012

Я собираюсь сказать то же, что и Райан: читабельность уступает только правильности. На самом деле, если вы студент, удобочитаемость может быть более важна, чем правильность.

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

Вот что я хочу, чтобы вы представили: сейчас 23:52, я устал, у меня болят глаза, и я читаю более сорока пяти решений одной и той же задачи, написанных студентами. Я ищу ЯСНОСТЬ, черт возьми. Если вы сможете написать свое решение таким образом, чтобы было ОЧЕВИДНО, что вы сделали это правильно, я собираюсь дать вам 100% и благословить ваше имя.

person John Clements    schedule 24.09.2012
comment
Я понимаю, откуда вы пришли, но чем старше я становлюсь, тем больше я ценю краткость, чем меньше кода я читаю, тем легче мне понять, что делает функция. Но это вопрос мнения, конечно. - person Andreas Brinck; 24.09.2012