2015-04-22 5 views
1

Как я понимаю, при вызове функций схема использует значение 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, указывающую на конец очереди). Поэтому я не вижу, как установленный автомобиль! копии этой переменной могут изменить часть автомобиля самого исходного объекта (переменная очереди).

Может кто-нибудь объяснить мне, как это работает? Является ли переменная очереди завернутой как адрес в пару?

ответ

4

Схема, как и большинство динамических языков, делает передачу по значению, но это эффективно передавая ссылки на объект (то, что язык, как Java, могли бы назвать их). На языке более низкого уровня, таком как C, это будет похоже на то, чтобы обойти указатель на значение. Сам указатель передается по значению, но вы можете использовать его для получения базового (общего) значения, на которое оно указывает.

В схеме номенклатура обычно относится к ней с точки зрения привязок. Связывание - это более или менее имя, которое ссылается на конкретное значение. Например, рассмотрим следующий код:

(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! просто корректирует то, на что ссылается данное привязку, а не само значение, поэтому другое связывание не изменяется.

+0

спасибо за объяснение и особенно зачем устанавливать! не влияет на другую привязку. Теперь гораздо яснее – philibertin

+1

Java также передается по значению. Это очень похоже на схему. – Sylwester

+0

@ Sylwester Да, это то, что я сказал в своем ответе. Большинство языков проходят по значению. Я не знаю, язык по умолчанию, хотя некоторые языки поддерживают его (на ум приходят C++ и PHP). –