Именованный пусть в схеме

Я пытаюсь написать цикл в схеме, используя named let. Я хотел бы иметь возможность выйти из итерации раньше, основываясь на различных критериях, а не всегда зацикливаться прямо в конце. По сути, я хотел бы иметь while, break и continue. Я вынужден использовать guile 1.8 по веским причинам, а guile 1.8 не реализует конструкцию R6RS while. Мой вопрос: должна ли рекурсия с использованием named let быть хвостовой рекурсией, и почему вы не можете перезапустить цикл до конца? [Нужен ли для этого пример кода?] Когда я пытаюсь рекурсивно использовать ранний выход в нескольких точках с операциями ввода-вывода, я неизменно считываю последний EOF и получаю непредсказуемое повреждение данных.


person andro    schedule 22.05.2017    source источник
comment
Было бы полезно показать, что вы уже пробовали. Вы упоминаете while, break и continue: это звучит так, как будто вы пытаетесь импортировать императивные идеи (стиль C) в неимперативный язык и, таким образом, пытаетесь написать чрезвычайно унидиоматическую схему.   -  person Norman Gray    schedule 22.05.2017
comment
(и в отношении ваших конкретных вопросов: нет, рекурсия не обязательно должна быть хвостовым вызовом; да, вы можете перезапустить «цикл» в любой момент; и да, пример кода поможет)   -  person Norman Gray    schedule 22.05.2017
comment
За исключением того, что Guile 2 считает целесообразным включить конструкцию while в качестве новой функции. Мой контекст на самом деле Guile. Guile действительно предназначен для интеграции с кодом C/C++, и такие императивные вещи действительно возникают время от времени. Мы не говорим здесь о «чистой» схеме (если вы понимаете, что я имею в виду).   -  person andro    schedule 22.05.2017
comment
Нет, но если ваша система ожидает, что вы будете управлять кодом C/C++ с помощью Guile, то она (предположительно) ожидает, что вы запрограммируете этот слой Guile идиоматическим способом. Если будете искать break и continue, то искать будете долго, так как непосредственных аналогов тем в схемах нет.   -  person Norman Gray    schedule 22.05.2017


Ответы (1)


(let name ((iter iter-expr) (arg1 expr1) (arg2 expr2))
  (cond
    (continue-predicate (name (next iter) arg1 arg2)))
    (break-predicate break-expression-value)
    (else (name (next iter) next-arg1-expression next-ar2-expression))))

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

Перерыв — это базовый случай.

Так что же такое while? Это имя let с предикатом разрыва и регистром по умолчанию.

Scheme на самом деле не имеет конструкции while. Если вы прочтете отчет, то увидите, что это просто синтаксический сахар (макрос), который превращается во что-то вроде имени let.

Вам нужно, чтобы он был хвостовым рекурсивным, если вы хотите иметь возможность выйти из него без выполнения всех предыдущих вычислений. Вы также можете использовать call/cc для предоставления продолжения выхода, которое, по сути, заставляет Scheme делать это за вас под капотом. Обычно call/cc довольно далеко для новичков, и для освоения требуется некоторое время, поэтому сделать ваши процедуры рекурсивными хвостами легче для понимания, чем делать что-то вроде этого:

(define (cars lists-of-pair)
  (call/cc (lambda (exit)
    (fold (lambda (e a)
            (if (pair? e)
                (cons (car e) a)
                (exit '()))) ; throw away continuations to make current result make it ()
          '()
          lists-of-pair)))

(cars '((1 2) (a b))) ; ==> (1 a)
(cars '((1 2) ()))    ; ==> ()
person Sylwester    schedule 22.05.2017
comment
Конечно, вы имеете в виду: «Так что же такое время? Это именованный let с предикатом continue и регистром по умолчанию.' - person andro; 22.05.2017
comment
@andro a while выполняет рекурсию, если предикат истинен, поэтому вы можете думать об этом как о рекурсии, если только не сработает отрицательный базовый случай. Таким образом, break с (not while-predicate) в качестве предиката. continue обычно имеет рекурсию, как и случай по умолчанию, но с меньшим количеством вычислений. - person Sylwester; 22.05.2017