Lisp 用于反转2-list列表元素的Scheme函数

Lisp 用于反转2-list列表元素的Scheme函数,lisp,scheme,Lisp,Scheme,这是EOPL的一个练习。 过程(反转lst)获取lst,lst是一个由两个列表组成的列表,并返回一个列表,每个列表都反转 (define invert (lambda (lst) (cond((null? lst ) '()) ((= 2 (rtn-len (car lst))) ( cons(swap-elem (car lst)) (invert (cdr lst)))) ("List i

这是EOPL的一个练习。 过程(反转lst)获取lst,lst是一个由两个列表组成的列表,并返回一个列表,每个列表都反转

(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 (cdr 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)))))
这似乎有效,但看起来非常冗长。这可以缩短或写得更优雅吗? 我如何停止处理任何一个不是2-list的单独元素?
此时,执行继续到下一个成员,如果当前成员不是2-List,则将当前成员替换为“List is not a 2-List”。

因此,您的invert版本似乎实际返回了不同拓扑的列表。如果您在
'((12)(34))
上执行
(反转…
,您将返回
'((2.1)(4.3))
,这是一个消费列表,而不是列表

我编写了一个版本的invert,它维护列表拓扑,但它不是尾部递归的,所以在递归时它将最终维护一个调用堆栈

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

如果您想要一个模仿您反转行为的版本,请将倒数第二行中的
列表
替换为
cons

如果您希望它在出现故障时尽早退出,请尝试调用/cc

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


使用当前continuation调用
(或简称
call/cc
)所做的是将函数被调用的点传递到函数中,这提供了一种类似于C中返回语句的方法。它还可以做更多的事情,因为您可以存储continuation,或将多个continuation传递到函数中,对于成功和失败,调用不同的过程。

EOPL语言提供了
EOPL:error
过程,以便提前退出并显示错误消息。本书第15页(第3版)介绍了这一点

EOPL语言还包括标准方案中的
map
过程。尽管本书中可能没有使用它,但您仍然可以使用它获得比显式递归更短的解决方案。您还可以使用Scheme的标准
长度
过程

#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))))

包含任意数量或顺序子列表的反向列表

(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))))))

非常感谢。如何处理列表并退出单个元素不是2列表的过程。您的过程只是跳过了额外的元素。非常感谢。虽然这超出了我目前的理解水平。:)