Почему вызов моей собственной прокручиваемой (уменьшенной) функции с помощью макроса влияет на будущие вызовы этой функции? - PullRequest
0 голосов
/ 03 сентября 2018

Справочная информация: Несколько недель назад я работал над проектом в схеме guile 1.8.8 и, немного подзабавив, я забыл о встроенном (reduce) функция, так что я катался самостоятельно. Чуть позже я столкнулся с тем, что казалось безнадежной ошибкой, когда вызов функции без побочных эффектов изменил ход остальной части программы (работающий должным образом и прошедший несколько модульных тестов против полного сбоя) ПОСЛЕ того, как функция имела давно вернулся. Несколько фрагментов кода, которые раньше возвращали что-то вроде (A B C D), теперь возвращали только (A), вызывая множество проблем.

Минимальный рабочий пример: После нескольких дней урезания я загнал проблему в небольшой фрагмент кода:

(define (my-reduce fun ls)
    (if (null? (cdr ls))
        (car ls)
        (my-reduce fun (cons (fun (car ls) (cadr ls))
                             (cddr ls)))))

(format #t "~a "  (my-reduce +   '(1 2 3)))
(format #t "~a "  (my-reduce or  '(1 2 3)))
(format #t "~a~%" (my-reduce +   '(1 2 3)))

Что выводит 6 1 1 вместо ожидаемого 6 1 6.

Дополнительные наблюдения:

  • Установка второй строки на + дает ожидаемое 6 6 6.
  • Установка второй строки на and приводит к 6 3 3.
  • Дополнительные строки + после них производят дополнительные 1 с или 3 с в зависимости от того, на что установлена ​​вторая строка. Итак, последовательность + or + + приводит к выводу 6 1 1 1.
  • Дополнительные строки and или or после первой НЕ переключайте выход обратно. Таким образом, если последовательность равна + and or +, вывод будет 6 3 3 3. Кажется, как только после того, как я передал or или and в (my-reduce), функция постоянно «застревает», имея это в качестве аргумента.
  • Я также заметил, что передача and или or во встроенную функцию (reduce) вызывает ошибку типа, поскольку они являются технически макросами, а не функциями.
  • В том же духе я заметил, что замена or на (lambda (x y) (or x y)) дает ожидаемый результат. Поэтому, похоже, что здесь важно то, что передача макросов в мою собственную функцию сокращения вызывает проблему.

Вопрос: Что здесь происходит? Почему вызов (my-reduce) с and или or вызывает такое неожиданное поведение? Связано ли это с тем, что эти «функции» на самом деле являются макросами?

Заранее спасибо за любую помощь. Этот действительно поставил меня в тупик!

1 Ответ

0 голосов
/ 03 сентября 2018

Вы сказали это сами, вы не можете передать and, or в качестве параметров, где ожидается функция, потому что они макросы и будут жаловаться на ошибку "неверный синтаксис". На самом деле, я не могу понять, как это работает для вас:

(my-reduce or '(1 2 3))

Единственный способ, которым я могу думать, это то, что вы переопределили and, or как функции где-то, и , что является источником проблем. В качестве примечания, my-reduce (понимается как операция сгиба вправо) может быть реализовано более стандартным способом, подобным этому:

(define (my-reduce fun ls)
  (if (null? (cdr ls))
      (car ls)
      (fun (car ls)
           (my-reduce fun (cdr ls)))))

Выше предполагается, что список не пустой, если это не всегда так, обычно в качестве параметра передается начальное значение:

(define (my-reduce fun init ls)
  (if (null? ls)
      init
      (fun (car ls)
           (my-reduce fun init (cdr ls)))))
...