首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用于反转2-list列表元素的方案函数

用于反转2-list列表元素的方案函数
EN

Stack Overflow用户
提问于 2011-02-18 22:58:56
回答 4查看 2.2K关注 0票数 1

这是一个来自EOPL的练习。过程(invert lst)获取lst,它是一个包含2个列表的列表,并返回一个列表,其中每个2列表都是颠倒的。

代码语言:javascript
运行
复制
(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 is not a 2-List“替换当前成员。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-02-19 06:36:53

EOPL语言为eopl:error过程提供了提前退出并显示错误消息的功能。这本书(第三版)的第15页介绍了这一点。

EOPL语言还包含来自标准方案的map过程。尽管它可能不会在书中使用,但您仍然可以使用它来获得比显式递归更短的解决方案。您也可以使用Scheme的标准length过程。

代码语言:javascript
运行
复制
#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))))
票数 1
EN

Stack Overflow用户

发布于 2011-02-18 23:16:37

所以看起来你的invert版本实际上返回了一个不同拓扑的列表。如果您在'((1 2) (3 4))上执行(invert ...),您将返回'((2 . 1) (4 . 3)),它是一个conses列表,而不是列表。

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

代码语言:javascript
运行
复制
(define (invert lst)
  (if (null? lst)
      lst
      (cons (list (cadar lst) (caar lst))
            (invert (cdr lst)))))

如果您想要一个模拟反转行为的版本,请在倒数第二行中用cons替换list

票数 1
EN

Stack Overflow用户

发布于 2011-02-18 23:32:00

如果您希望它在失败时尽早退出,可以尝试call/cc。

代码语言:javascript
运行
复制
(call-with-current-continuation
  (lambda (exit)
    (for-each (lambda (x)
                (if (negative? x)
                    (exit x)))
              '(54 0 37 -3 245 19))
    #t))  
                          ===>  -3

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

call-with-current-continuation (简称为call/cc )所做的是将函数调用到函数中的点传递给函数,这提供了一种类似于C语言中的返回语句的方法。它还可以做更多的事情,因为您可以存储延续,或者将多个延续传递到一个函数中,并在成功和失败时调用不同的一个。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5042809

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档