LINUX.ORG.RU

set! в scheme


0

0

Есть функция:

  (define (loop x y)
    (if (null? x)
        y
        (let ((temp (cdr x)))
          (set-cdr! x y)
          (loop temp x))))

где set-cdr:

(define (set-cdr! x new-cdr)
  (set! x (cons (car x) new-cdr))
   x)

Никак не могу понять, почему (loop '(a b c d) '()) выдаёт '(d), а не '(d c b a).
★★★★★

Во-первых, почему бы не использовать чисто функциональный стиль:

(define (myloop x y)
  (if (null? x) y
      (loop (cdr x) (cons (car x) y))))

Во-вторых, приведенный код для loop работает как ожидается, если не 
определять свой set-cdr! (зачем это делать, если он есть в стандарте 
R5RS?). Ошибка же в приведенном set-cdr!

(define (set-cdr! x new-cdr)
  (set! x (cons (car x) new-cdr))
   x)

set! устанавливает биндит x к значению (cons (car x) new-cdr) внутри 
окружения set-cdr!, например:

(define (play! x) 
  (begin (set! x "foo") (display x)))

(define q "bar")

> (play! q) 
foo
> q
"bar"

grob ★★★★★
()
Ответ на: комментарий от grob

в первом куске кода loop -> myloop или наоборот :)

grob ★★★★★
()
Ответ на: комментарий от grob

>Во-первых, почему бы не использовать чисто функциональный стиль:

>(define (myloop x y)
>  (if (null? x) y
>      (loop (cdr x) (cons (car x) y))))

Конечно, на схеме логичнее сделать именно так, просто это пример из SICP, глава "Modeling with mutable data".

>Во-вторых, приведенный код для loop работает как ожидается, если не 
>определять свой set-cdr! (зачем это делать, если он есть в стандарте 
>R5RS?). Ошибка же в приведенном set-cdr!

Ну конечно, вот где я сглупил, решил определить эти функции, хотя в тексте не было указаний на этот счёт. Посмотрел на возвращаемое значение и почему-то решил, что они работают правильно :) Про модель вычисления с set! (окружения, связи и т.п.) было рассказано в предыдущей главе. Я просто очень сильно стормозил :(

Однако, стандартные set-car! и set-cdr! работают как-то странно
(define x '((a b) c d))
(define y '(e f))
(set-car! x y) установит x в '((e f) c d);
(set-cdr! x y) установит x в '((a b) e f).
Но,
(define u '(a b c d))
(define v '(e f))
(set-cdr! u v), как и ожидалось, установит u в '(a e f), а вот
(set-car! u v) установит u в '((e f)) (!), а не в '((e f) b c d).
Методом тыка удалось выяснить, что (car u) и v должны быть структурно одинаковыми списками.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

> (define x '((a b) c d))
> (define y '(e f))
> (set-car! x y) установит x в '((e f) c d);
> (set-cdr! x y) установит x в '((a b) e f).

тут-то все ОК

> (define u '(a b c d))
> (define v '(e f))
> (set-cdr! u v), как и ожидалось, установит u в '(a e f), а вот
> (set-car! u v) установит u в '((e f)) (!), а не в '((e f) b c d).

guile> (define u '(a b c d))
guile> (define v '(e f))
guile> (set-car! u v)
guile> u
((e f) b c d)

grob ★★★★★
()
Ответ на: комментарий от grob

Опять я что-то напутал. Сейчас в drscheme всё работает как надо. Наверное, тогда я что-то совсем не то сделал. Надо больше спать.

seiken ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.