Scheme function to reverse a list

后端 未结 4 1299
甜味超标
甜味超标 2021-01-16 13:36

For my programming languages class I\'m supposed to write a function in Scheme to reverse a list without using the pre-made reverse function. So far what I got was

相关标签:
4条回答
  • 2021-01-16 13:46

    Step through the list and keep appending the car of the list to the recursive call.

    (define (reverseList lst)
    (COND
    ((NULL? lst) '())
    (ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR      lst))))
    ))
    
    0 讨论(0)
  • 2021-01-16 13:50

    You are half way there. The order of the elements in your result is correct, only the structure needs fixing.

    What you want is to perform this transformation:

     (((() . c) . b) . a)           ; input
     --------------------
     (((() . c) . b) . a)   ()      ; trans-
      ((() . c) . b)       (a)      ;      for-
       (() . c)          (b a)      ;         mation
        ()             (c b a)      ;               steps
          --------------------
                       (c b a)      ;               result
    

    This is easy to code. The car and cdr of the interim value are immediately available to us. At each step, the next interim-result is constructed by (cons (cdr interim-value) interim-result), and interim-result starts up as an empty list, because this is what we construct here - a list:

    (define (transform-rev input)
       (let step  ( (interim-value    input)       ; initial set-up of 
                    (interim-result    '() ) )     ;  the two loop variables
         (if (null? interim-value)
           interim-result                  ; return it in the end, or else
           (step  (car interim-value)      ; go on with the next interim value
                  (cons                    ;      and the next interim result
                      (... what goes here? ...)
                      interim-result )))))
    

    interim-result serves as an accumulator. This is what's known as "accumulator technique". step represents a loop's step coded with "named-let" syntax.

    So overall reverse is

    (define (my-reverse lst)
       (transform-rev 
           (reverseList lst)))
    

    Can you tweak transform-rev so that it is able to accept the original list as an input, and thus skip the reverseList call? You only need to change the data-access parts, i.e. how you get the next interim value, and what you add into the interim result.

    0 讨论(0)
  • 2021-01-16 14:08
    (define (my-reverse L)
     (fold cons '() L)) ;;left fold
    
    0 讨论(0)
  • 2021-01-16 14:10

    The problem with your implementation is that cons isn't receiving a list as its second parameter, so the answer you're building isn't a proper list, remember: a proper list is constructed by consing an element with a list, and the last list is empty.

    One possible workaround for this is to use a helper function that builds the answer in an accumulator parameter, consing the elements in reverse - incidentally, this solution is tail recursive:

    (define (reverse lst)
      (reverse-helper lst '()))
    
    (define (reverse-helper lst acc)
      (if (null? lst)
          acc
          (reverse-helper (cdr lst) (cons (car lst) acc))))
    
    (reverse '(1 2 3 4 5))
    => '(5 4 3 2 1)
    
    0 讨论(0)
提交回复
热议问题