2014-09-01 5 views
3

я получил функцию, чтобы изменить порядок элементов в списке, например,Как изменить порядок элементов списка на схеме

(define (rvsl sequence) 
    (foldl (lambda (x y) 
      (cons y x)) 
     '() sequence)) 

Однако, когда я бежал его в DrRacket с входом

(rvsl (list 2 3 4)) 

DrRacket сказал мне это

cons: second argument must be a list, but received empty and 2 

Может кто-нибудь пожалуйста, дайте мне некоторые идеи для ее решения?

Заранее благодарен!

+1

Просто используйте '(cons x y)' вместо '(cons y x)'. –

+0

Вы определили rvsl для принятия двух аргументов и только передали его, когда вы его использовали.Вы можете передать либо два аргумента с самого начала, либо создать другую процедуру, которая передаст правильное количество аргументов в rvsl. – malisper

ответ

2

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

Сказав, что, изменив список, используя foldl немного проще, и вам не нужно использовать append вообще - на самом деле, это плохая практика использования append когда cons хватает:

(define (rvsl sequence) 
    (foldl cons 
     '() 
     sequence)) 

Почему это работает? давайте перепишем функцию быть более четко на этот раз:

(define (rvsl sequence) 
    (foldl (lambda (current accumulated) 
      (cons current accumulated)) 
     '() 
     sequence)) 

Теперь мы можем видеть, что lambda процедуры получает два параметра: current элемента в списке ввода, а значение accumulated до сих пор - хорошие имена параметров делают все разница в мире! это намного, гораздо яснее, чем вызов параметров x и y, в которых ничего не говорится о них.

В этом случае мы просто хотим, чтобы cons текущий элемент в начале накопленного значения (который начинается как пустой список), следовательно, создавая в качестве выходного списка обратный список. Учитывая, что процедура lambda получает два параметра и передает их в том же порядке, что и cons, мы можем упростить все это и просто передать процедуру cons в качестве параметра.

0

У вас нет использовать foldl или что-нибудь еще, собственно, для определения функции rev; сама rev функции достаточно:

(define (rev ls)         ; rev [] = [] 
    (cond           ; rev [x] = [x] 
    ((null? ls) ls)        ; rev (x:xs) 
    ((null? (rest ls)) ls)      ; | (a:b) <- rev xs 
    (else          ; = a : rev (x : rev b) 
     (cons (first (rev (rest ls))) 
      (rev (cons (first ls) 
         (rev (rest (rev (rest ls)))))))))) 

(комментарии в эквациональном соответствии шаблона псевдокода). Вывод и обсуждение here.

(Редактировать: это, очевидно, код игрушки, просто чтобы отточить вашу схему-фу).

1

Вот простая версия, использующая внутреннюю итерационную процедуру.

(define (rev lst) 
    (define (iter accum lst) 
    (if (null? lst) 
     accum 
     (iter (cons (car lst) accum) 
       (cdr lst)))) 
    (iter '() lst))