开发者

Scheme Function to reverse elements of list of 2-list

开发者 https://www.devze.com 2023-02-11 17:12 出处:网络
This is an exercise from EOPL. Procedure (invert lst) takes lst which is a list of 2-lists and returns a list with each 2-list reversed.

This is an exercise from EOPL. Procedure (invert lst) takes lst which is a list of 2-lists and returns a list with each 2-list reversed.

(define invert
  (lambda (lst)
    (cond((null? lst )
         '())
       ((= 2 (rtn-len (car lst)))
        ( cons(swap-elem (car lst))
               (invert (cdr lst))))
       ("List is not a 2-List"))))

;; Auxiliry Procedure swap-elements of 2 element list

(define swap-elem
  (lambda (lst)
    (cons (car (c开发者_如何学Godr lst))
          (car lst))))

;; returns lengh of the list by calling
(define rtn-len
  (lambda (lst)
    (calc-len lst 0)))        

;; calculate length of the list
(define calc-len
  (lambda (lst n)
    (if (null? lst)
        n
        (calc-len (cdr lst) (+ n 1)))))

This seems to work however looks very verbose. Can this be shortened or written in more elegant way ? How I can halt the processing in any of the individual element is not a 2-list? At the moment execution proceed to next member and replacing current member with "List is not a 2-List" if current member is not a 2-list.


The EOPL language provides the eopl:error procedure to exit early with an error message. It is introduced on page 15 of the book (3rd ed.).

The EOPL language does also include the map procedure from standard Scheme. Though it may not be used in the book, you can still use it to get a much shorter solution than one with explicit recursion. Also you can use Scheme's standard length procedure.

#lang eopl

(define invert
  (lambda (lst)
    (map swap-elem lst)))

;; Auxiliary Procedure swap-elements of 2 element list

(define swap-elem
  (lambda (lst)
    (if (= 2 (length lst))
        (list (cadr lst)
              (car lst))
        (eopl:error 'swap-elem
                    "List ~s is not a 2-List~%" lst))))


So it seems that your version of invert actually returns a list of different topology. If you execute (invert ...) on '((1 2) (3 4)), you'll get back '((2 . 1) (4 . 3)), which is a list of conses, not of lists.

I wrote a version of invert that maintains list topology, but it is not tail-recursive so it will end up maintaining a call stack while it's recursing.

(define (invert lst)
  (if (null? lst)
      lst
      (cons (list (cadar lst) (caar lst))
            (invert (cdr lst)))))

If you want a version that mimics your invert behavior, replace list with cons in second to last line.


If you want it to exit early on failure, try call/cc.

(call-with-current-continuation
  (lambda (exit)
    (for-each (lambda (x)
                (if (negative? x)
                    (exit x)))
              '(54 0 37 -3 245 19))
    #t))  
                          ===>  -3

(Taken from http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_idx_566)

What call-with-current-continuation (or call/cc, for short) does is pass the point where the function was called in into the function, which provides a way to have something analogous to a return statement in C. It can also do much more, as you can store continuations, or pass more than one into a function, with a different one being called for success and for failure.


Reverse list containing any number or order of sub-lists inside.

(define (reverse! lst)
  (if (null? lst) lst
    (if (list? (car lst))
      (append (reverse! (cdr lst)) (cons (reverse! (car lst)) '()))
      (append (reverse! (cdr lst)) (list (car lst))))))
0

精彩评论

暂无评论...
验证码 换一张
取 消