#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 и не допускает пустой список. Я уверен, что вы можете применить мое предложение к своему решению, чтобы соответствовать этой спецификации.