Scheme 寻找更干净的方法,使关联列表中的数字列表
我想写一个程序,它将以“(071014)的形式接受一个列表,并将其转换为一个列表”((0.7)(7.10)(10.14))。下面的过程正好可以做到这一点。我认为它相当混乱,找不到更简单的方法来写它。也许我可以用一个内置的球拍功能来做这个Scheme 寻找更干净的方法,使关联列表中的数字列表,scheme,racket,Scheme,Racket,我想写一个程序,它将以“(071014)的形式接受一个列表,并将其转换为一个列表”((0.7)(7.10)(10.14))。下面的过程正好可以做到这一点。我认为它相当混乱,找不到更简单的方法来写它。也许我可以用一个内置的球拍功能来做这个 (define (simplify-path path) (if (null? (cddr path)) (cons (cons (car path) (cadr path)) '()) (begin (cons (con
(define (simplify-path path)
(if (null? (cddr path))
(cons (cons (car path) (cadr path)) '())
(begin (cons (cons (car path) (cadr path))
(simplify-path (cdr path))))))
使用球拍,我们可以做到:
(define (simplify-path path)
(map cons
(drop-right path 1)
(rest path)))
它按预期工作:
(simplify-path '(0 7 10 14))
=> '((0 . 7) (7 . 10) (10 . 14))
我也是
- 与
相比,map
可以采用两种不同长度的列表-缩短到最短的长度for/list
- 以麻省理工学院的方案编写
(define list->assocs
(lambda (l)
(define pair-first-second
(lambda (l)
(cons (car l) (cadr l))))
(define iter
(lambda (l k)
(if (eq? '() (cddr l))
(k (pair-first-second l))
(iter (cdr l)
(lambda (r)
(k (cons (pair-first-second l) r)))))))
(if (or (eq? '() l)
(eq? '() (cdr l)))
l
(iter l
(lambda (x) x)))))
(list->assocs '(0 7 10 14))
然而,
iter
真的会是迭代的吗?继续引用的是l
,该引用在哪里iter
的调用框架不能重复使用,或者所有的l
都是相同的。在这里,iter
真的不能进行TC优化吗?但这种情况在编写CPS时很常见,就像您在这里所做的那样。这是否意味着CPS代码(几乎)从未有过TCO?我突然对这一切产生了严重的怀疑…@任性iter是迭代的。它的复杂性是O(长度l)
,它跨越l
两次,一次向前,一次向后。延续指的是当我们在第二次通过时,从列表的末尾返回到列表的头部时的l
。代码在两个过程中都是尾部调用的,当它向前运行时,堆会增长;当它通过k
向后运行时,它也是尾部递归的。iter只在列表上运行一次,向末尾前进。当它到达终点时,它已经构建了一条O(n)长的lambdas链。那些lambda都是尾部调用前一个。他们正在从输入列表的末尾构建结果。这一点很清楚。但它们各自引用自己的l
(沿着输入列表)。问题:所有这些l
s指向/指的是哪里?它不能直接指向相应调用的iter的框架,这些框架已经消失,重新使用,因为iter是TR。我猜当创建闭包时,框架会被复制。这就是答案。:)@意志力所有这些l
s指向/指的是哪里?它们指的是本地的lambda(lk)
,实际上它们与lambda(l)
中初始l
的CDR
是相同的指针,但是k
的闭包的每一帧看起来都像((l.指向l的某个指针)(k.指向封闭延续的指针))((l.初始列表)(iter.pointer-to-func)(第一对第二对。pointer-to-func))…)
等。所谓“本地lambda”是指(定义iter(lambda(l k)…
?我称之为“iter调用框架”中的一个.我想它必须在创建闭包时复制。不能引用框架本身,因为它已成为TCO的一部分。这就是我一直在努力解决的问题。
(define list->assocs
(lambda (l)
(define pair-first-second
(lambda (l)
(cons (car l) (cadr l))))
(define iter
(lambda (l k)
(if (eq? '() (cddr l))
(k (pair-first-second l))
(iter (cdr l)
(lambda (r)
(k (cons (pair-first-second l) r)))))))
(if (or (eq? '() l)
(eq? '() (cdr l)))
l
(iter l
(lambda (x) x)))))
(list->assocs '(0 7 10 14))