Scheme - 在begin语句结尾处递归参数?

时间:2014-12-19 09:50:20

标签: recursion scheme racket

我想要一些关于“开始”+函数+调用变量的机制的澄清或资源,就像cond结构和以下函数中对“node”的调用一样。

坦率地说,我不明白为什么未能将循环调回“节点”会导致错误,哪个节点不再是节点对象,如下所述。

事实上,虽然我直觉地认为如果我称“树”改变“节点”的值我然后应该恢复原始值,我不明白为什么这需要在第二次检查时进行,因为如果“节点”没有在那里改变那么值..

我猜我的疑问是关于“开始”的构造,因为如果在循环函数的情况下我理解循环必须在“开始”语句的末尾被调用我不明白是什么应该要求一个论点..

(define tree
  (lambda (node value)
    (cond
      ((null? node)
       (make-node value)) ; if I insert node at the end of this line I just get () as an output
      ((= value (node-value node))
       (node-counter-set! node (+ 1 (node-counter node)))
       node) ; in this position in Dr. Racket a simple ")" would do, but the Petit Chez Scheme implementation that we use for tests in class requires the call to "node"
      ((< value (node-value node))
       (node-left-set! node (tree (node-left node) value))
       node)
      (else
       (node-right-set! node (tree (node-right node) value))
       node)
      )))

这是包含以下内容的更大系统的一部分:

(define build
  (lambda (root lon)
    (cond
      ((null? lon)
       lon)
      (else
       (build (tree root (car lon)) (cdr lon))
       ))))

(define make-node
  (lambda (value)
    (vector '() value '() 1)
    ))

(define node-counter-set!
  (lambda (node value)
    (vector-set! node 3 value)
    ))

(define node-left-set!
  (lambda (node value)
    (vector-set! node 0 value)
    ))

(define node-right-set!
  (lambda (node value)
    (vector-set! node 2 value)
    ))

(define node-value
  (lambda (node)
    (vector-ref node 1)
    ))

(define node-counter
  (lambda (node)
    (vector-ref node 3)
    ))

(define node-left
  (lambda (node)
    (vector-ref node 0)
    ))

(define node-right
  (lambda (node)
    (vector-ref node 2)
    ))

3 个答案:

答案 0 :(得分:3)

  

&#34;我该如何关闭begin语句?&#34;

使用您想要的任何表达式。在计算时,该表达式的值将作为整个begin表达式的值返回。

Scheme是面向表达式的语言。其中的每个代码片段 - 每个表单 - 都是一个表达式,而不是语句 - 它有一些价值。

变量不被称为&#34;它们被引用&#34;它们的被使用。

有时变量引用的值是&#34;变异&#34; - 改变了。 E.g。

(vector-set! var ... )

更改var引用的向量的实际内容。如果你要写(set! var 2),你会改变变量的绑定,即你会改变它引用的对象(迄今为止,数字 2 )。

使用这种变异操作的函数除了按照所有函数返回一些值之外,还被认为具有&#34;(侧)效果&#34; 。这里的效果将是实际内存驻留对象的改变,一个向量,可能在程序的其他部分可以访问。

答案 1 :(得分:2)

begin块的值是块

中最后一个表达式的值
> (define x (begin (print "hello") 3 2 1))
"hello"
> x
1

关于向量变异表达式的值的实现可能有所不同 - 有些返回修改后的向量,而有些返回void或类似的东西。
因此,在你的tree过程中,一些实现将要求你明确地给出node作为表达式的值(并且这是一个明确的好习惯,而不是依赖于副作用,无论如何)。 / p>

答案 2 :(得分:2)

通常使用像vector-set!这样的变异过程,表达式会计算出一些未定义的值。未定义我们的意思是实施者可以选择放置他们想要的东西。然后,大多数实现选择一个对象为&#34; undefined&#34;对象,但有些人可能会选择返回突变的对象,使你不必在那个实现中明确地执行它。请注意,如果您使用特定于实现的功能,则会获得特定于实现的代码,而不是符合Scheme报告的内容!

如果您希望node-counter-set!评估您在过程中执行此操作的参数:

(define (node-counter-set! node value)
    (vector-set! node 3 value) ; set value on the node. It returns an undefined value
    node)                      ; last expression in the explicit begin we return the node

<强> BEGIN

begin是一个特殊形式,它按顺序计算表达式,除了最后一个表达式之外,我们只丢弃结果。因此,为了使这些表达有用,他们需要有像突变或输入/输出这样的副作用。

begin个地方没有直接放置。例如。过程的主体具有隐式begin

(lambda (x y)
  (display x)
  (newline)
  (display y)
  (newline)
  (+ x y)) ; procedure returns the sum of it's arguments but have lots of sife effects first

cond每个字词可能有多个结果,这是一个明确的begin

(cond
  ((= x y) (display "X and Y are same number") (+ x y))
  ...)

实际上它的语法糖是:

(if (= x y) 
    (begin (display "X and Y are same number") (+ x y))
    ...)