Схема — Как мне выполнить цикл анонимной функции?

#function #loops #scheme #higher-order-functions #anonymous

#функция #циклы #схема #функции более высокого порядка #Аноним

Вопрос:

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

Обычная версия функции:

 (define (accumulate proc id lst)
  (cond ((null? lst) id)
    ((eqv? (cdr lst) '()) (car lst))
    (else (proc (car lst) (accumulate proc id (cdr lst))))))
  

Версия функции более высокого порядка (неполная):

 (define (acc-proc proc id)
(lambda (lst)
(cond ((null? lst) id)
      ((null? (cdr lst)) (car lst))
      (else 
  

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

Я новичок в схеме, поэтому простите меня, если мои решения плохие. Может быть, есть лучший способ сделать это без зацикливания? Я понятия не имею, что вставить в этот оператор else…

Ответ №1:

Обратите внимание, что в вашей исходной функции есть ошибка: ваш второй случай означает, что вы игнорируете id все, кроме пустого списка:

 > (accumulate   34 '(1 2 3))
6
> (accumulate   34 '())
34
  

Вам нужны только два случая; пустые и непустые списки.

Для реальной проблемы: если «анонимная» часть не является существенной, вы можете использовать локальную именованную функцию:

 (define (acc-proc proc id)
  (define (recurse lst)
    (if (null? lst)
        id
        (proc (car lst) (recurse (cdr lst)))))
  recurse)
  

Если важна анонимность, вам нужно использовать маршрут лямбда-исчисления и использовать комбинатор с фиксированной точкой.

Комментарии:

1. Это не ошибка. Предполагается, что во втором случае идентификатор игнорируется. Если список пуст, он вернет идентификатор.

2. (накопить 0 ‘())

3. @Schytheron и задача описывает, что должно произойти, если это шаг перед пустым списком, как у вас в коде?

4. В нем говорится: «Если в списке есть только один элемент, то должен быть возвращен первый элемент. Если список содержит более одного элемента, процедура должна быть применена к первому элементу, а результат накапливается для остальной части списка »

5. @Schytheron Вау. Это … «явно нестандартно» (чтобы избежать ругани) и не так, как большинство людей ожидают accumulate работать. Обычно описываемый вами вариант не имеет параметра identity и не допускает пустой список. Я уверен, что вы можете применить мое предложение к своему решению, чтобы соответствовать этой спецификации.