我正在尝试在我的CS类的Scheme(R5RS)中编写一个过程,它接受一个表达式(符号或列表)作为参数,并返回一个列表(1)所有可能的表达式通过使用car和cdr在表达式上形成和(2)以及证明如何获得原始表达的这些组分中的每一种的表达。如果一件作品可以多种方式获得,则应该多次退回。
Examples
(pieces '()) => ((() x))
(pieces 'apple) => ((apple x))
(pieces '(apple)) => (((apple) x) (apple (car x)) (() (cdr x)))
(pieces '(a (b c))) =>
(((a (b c)) x)
(a (car x))
(((b c)) (cdr x))
((b c) (car (cdr x)))
(b (car (car (cdr x))))
((c) (cdr (car (cdr x))))
(c (car (cdr (car (cdr x)))))
(() (cdr (cdr (car (cdr x)))))
(() (cdr (cdr x))))
由于我们刚开始使用Scheme,因此我们仅限于此分配的相当基本的语法。这是我到目前为止所做的:
(define pieces
(lambda (exp)
(cond
((symbol? exp)
(list exp 'x))
((null? exp)
(list '() 'x))
((list? exp)
(let ((b (pieces (car exp))) (c (pieces (cdr exp))))
(list exp 'x b c))))))
(pieces '()) => (() x)
(pieces 'apple) => (apple x)
(pieces '(apple)) => ((apple) x (apple x) (() x))
(pieces '(a (b c))) => ((a (b c)) x (a x) (((b c)) x ((b c) x (b x) ((c) x (c x) (() x)))
(() x)))
该过程返回所有正确的元素,但每次递归都会导致组件嵌套在另一个列表中。有没有办法阻止它?
另外,我不知道从哪里开始解决问题的第二部分(显示每个元素是如何使用car和cdr从原始元素中获得的)。我已经尝试了一百万种不同的方法,而且它们都没有接近工作。如果有人对如何实现该功能有任何提示或建议,我真的很感激。非常感谢。
答案 0 :(得分:1)
(pieces 'apple) => (apple x)
但它应该是((apple x))
,对吗?您应该得到一个列表,其中第一个也是唯一一个元素是列表(apple x)
。
终止递归的cond子句(exp是符号或null)返回应该列在列表中的项,而在car
和cdr
上重复的子句尝试创建项列表。由于pieces
可以返回项目和项目列表,因此很难从它返回的值中列出项目列表:当您执行(list exp 'x b c)
时,您不知道是否b
1}}和c
是应该进入列表或项目列表的项目。
如果您确保pieces
始终返回项目列表(例如(list (list exp 'x))
),则会更加轻松。当您重复car
和cdr
时,您希望执行append
列表a
和b
之类的操作并添加“当前”({{1} })项目到该列表(可能与(list exp 'x)
或其他)。
对于第二部分,cons
必须知道它是如何到达当前项目的。您可以使pieces
将当前项目的“路径”作为(可能是可选的)参数。如果路径是一个列表,那么当您在pieces
上致电pieces
时,您可以将(car exp)
符号添加到您要作为参数发送的路径,并为car
添加(cdr exp)
可以添加符号cdr
。然后使用该路径创建一些好的东西,以替换'x
中的(list exp 'x)
。
答案 1 :(得分:0)
我知道这不是Scheme,但是看一下相似的语言会有所帮助。我这样做更多是为了练习自己,所以带上一滴盐,但它似乎正在完成你所追求的:
(defun parse-list (whatever)
(labels ((pieces (expression &optional path)
(cond
((null expression)
`((,path . nil)))
((listp expression)
(append (list
`(,path . ,expression))
(pieces (car expression)
(cons 'car path))
(pieces (cdr expression)
(cons 'cdr path))))
(t `((,path . ,expression))))))
(dolist (output (pieces whatever))
(format t "path ~a => result ~a~&"
(car output) (cdr output)))))
(parse-list '(a (b c)))
然后产生这个输出:
path NIL => result (A (B C))
path (CAR) => result A
path (CDR) => result ((B C))
path (CAR CDR) => result (B C)
path (CAR CAR CDR) => result B
path (CDR CAR CDR) => result (C)
path (CAR CDR CAR CDR) => result C
path (CDR CDR CAR CDR) => result NIL
path (CDR CDR) => result NIL
抱歉,我无法更好地获得SO代码格式:)