据我所知,Scheme在调用函数时使用pass-by-value。我看到的队列的一个实现定义如下(yet another scheme tutorial):
(define (make-queue)
(cons '() '()))
(define (enqueue! queue obj)
(let ((lobj (cons obj '())))
(if (null? (car queue))
(begin
(set-car! queue lobj)
(set-cdr! queue lobj))
(begin
(set-cdr! (cdr queue) lobj)
(set-cdr! queue lobj)))
(car queue)))
然后创建队列,并将其传递给enqueue!
:
(define q (make-queue))
;Value: q
(enqueue! q 'a)
;Value 12: (a)
如果只传递值,那么传递给函数的队列变量如何修改?我读到使用set-box和unbox可以做到这一点,但事实并非如此。
根据我的理解,队列变量是一对(汽车部分指向队列的头部,cdr部分指向队列的末尾)。所以我不知道如何定车!该变量的副本可以改变原始对象本身的汽车部分(队列变量)。
有人可以向我解释它是如何运作的吗?队列变量是否包装为一对地址?
答案 0 :(得分:4)
Scheme与大多数动态语言一样,按传递值,但它有效地传递对象引用(像Java这样的语言会称之为)。在像C这样的低级语言中,它就像传递指向值的指针一样。指针本身按值传递,但您可以使用它来获取它指向的基础(共享)值。
在Scheme中,命名法通常根据绑定来指代这一点。绑定或多或少是引用特定值的名称。例如,请考虑以下代码:
(let* ((a '(1 . 2))
(b a))
(set-car! b 3)
(set! b 'something-else)
(display a)
(newline)
(display b))
这将打印以下内容:
(3 . 2)
something-else
在该示例中,a
和b
是两个不同的绑定,它们绑定到相同的值,一个cons对。使用set-car!
修改基础值,该对本身。相反,set!
只是调整给定绑定所指的内容,而不是值本身,因此另一个绑定不受影响。