Scheme

时间:2016-07-26 14:10:09

标签: variables graph scheme

我试图在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节点也会删除对给定节点的所有引用。

1 个答案:

答案 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中,建议的样式是避免变量变量,如果需要更改某些内容,则创建一个包含修改的新对象(本例中为节点列表),并将其传递给接收它的过程。参数,我们可以根据需要多次执行此操作,可能以递归方式执行。