Эта проблема может быть решена намного проще с apply
, используя тот факт, что операторы сравнения получают переменное число аргументов:
(apply < '(1 2 3 4))
=> #t
(apply < '(1 2 5 4))
=> #f
UPDATE
Для этой задачи, в частности, foldr
не является правильным инструментом для работы (хотя это не невозможно, так как у вас есть demonstrated) - нет значения, которое нужно «накапливать», пока перебирается список, список либо упорядочен, либо нет для данного предиката ,
Из комментариев я понимаю, что процедура pre?
может быть произвольной lambda
, которая получает ровно два параметра.
Возможным решением было бы создать al-список всех пар последовательных элементов и проверить, верно ли предикат для всех из них. Обратите внимание, что последний элемент не будет иметь соответствующую пару, поэтому нам нужно исключить его из списка пар. Для этого я буду определять специальную zip
процедуру, которая, учитывая два входных списков, заботится о создании списка пар, принимая во внимание тот факт, что списки могут быть разной длины:
(define (zip lst1 lst2)
(if (or (null? lst1) (null? lst2))
'()
(cons (list (car lst1) (car lst2))
(zip (cdr lst1) (cdr lst2)))))
(zip '(1 2 3) '(2 3))
=> '((1 2) (2 3))
Теперь Собираем все вместе мы сможем решить исходную задачу так:
(define (accum? lst pre?)
(andmap (lambda (tuple)
(pre? (car tuple) (cadr tuple)))
(zip lst (cdr lst))))
Имейте в виду, что это не будет работать для пустых списков, но это тривиально, чтобы добавить специальный случай для этого. Теперь сравнение может быть сделано с произвольным lambdas
:?
(accum? '(1 2 3) (lambda (a b) (= a (- b 1))))
=> #t
Да, это лучше использовать 'предварительно' непосредственно, обратите внимание, что 'if' заканчивается возвращением так же, как' предварительно ' –