我试图在Scheme中实现非常简单的图形:
'( (node1 '(node2 node3) ) (node2 '() ) (node3 '()) )
列表列表,但现在我需要将图表列表存储在变量中。 我尝试使用define
(define graph '())
然后使用此过程向列表中添加更多节点。
(define (add-node name children) (list graph (list name children)))
按预期工作:
(add-node 1 '(2 3))
返回:'(()(1(2 3)))
问题是我无法使用新添加的节点更新图表。 试图重新定义图形导致“已经定义的错误”,绑定使用let / let!导致“无法修改常量错误”
非常感谢任何帮助或建议。
编辑: 感谢@ÓscarLópez
我想出了解决问题的方法。 我不是计划大师,但这是我的代码(至少它工作:))
;Define the empty graph
(define graph '())
; Graph mutator. All modify operations use this procedure
(define (modify-graph newGraph)
(set! graph newGraph)
graph)
; Adds a node to the graph ( name '(chidren) ) (add-node 1 '(2 3))
(define (add-node name children)
(define (add-node-helper name children graph)
(cons (list name children) graph))
(modify-graph (add-node-helper name children graph)))
; Generic procedure which removes elements from list that match certain condition
(define (remove-element elements condition?)
(cond ((empty? elements) elements)
((condition? (car elements)) (remove-element (cdr elements) condition?))
(else (cons (car elements) (remove-element (cdr elements) condition? ))))
)
; Removes a node, and all references to it.
(define (remove name)
(define (remove-node name)
(define (condition? element)
(eq? (car element) name))
(remove-element graph condition?))
(define (remove-all-refs name)
(define (remove-child name node)
(define (condition? element)
(eq? name element))
(cons (car node) (list (remove-element (cadr node) condition?))))
(define (remove-all-refs-helper name graph)
(cond ((empty? graph) graph)
(else (cons (remove-child name (car graph)) (remove-all-refs-helper name (cdr graph))))))
(remove-all-refs-helper name graph))
(modify-graph (remove-node name))
(modify-graph (remove-all-refs name))
)
最终结果是:
(add-node 1 '(2 3))
(add-node 3 '(5 6))
(add-node 2 '(7 8 9 10 11))
> graph ;-> '((2 (7 8 9 10 11)) (3 (5 6)) (1 (2 3)))
remove节点也会删除对给定节点的所有引用。
答案 0 :(得分:3)
您应该避免改变全局定义的数据,并且您的add-node
程序看起来并不正确(每次调用图表时,图表都会嵌套在列表中)。我建议这个:
(define (add-node name children graph)
(cons (list name children) graph))
即:将图形作为参数传递,并返回包含新添加节点的列表。然后以递归方式传递修改后的图形(首选)或修改变量及其值(不鼓励):
; good idea
(procedure-that-modifies-graph (add-node name children graph))
; not recommended
(let ((graph '()))
(set! graph (procedure-that-modifies graph (add-node name children))))
在Scheme中,建议的样式是避免变量变量,如果需要更改某些内容,则创建一个包含修改的新对象(本例中为节点列表),并将其传递给接收它的过程。参数,我们可以根据需要多次执行此操作,可能以递归方式执行。