Я получил неожиданный результат при переопределении оператора +
в программе схемы с использованием guile
. Я должен отметить, что это произошло во время экспериментов, чтобы попытаться понять язык; здесь нет попыток написать полезную программу.
Вот код:
(define (f a b) 4)
(define (show)
(display (+ 2 2)) (display ",") (display (f 2 2)) (newline))
(show)
; guile & mit-scheme: "4,4"
(define (+ a b) 5)
(define (f a b) 5)
(show)
; mit-scheme: "5,5"
; guile: "4,5" - this "4" is the unexpected result
(define (show)
(display (+ 2 2)) (display ",") (display (f 2 2)) (newline))
(show)
; guile & mit-scheme: "5,5"
В guile
функция show
использует предопределенное определение +
даже после того, как я его переопределил, хотя и использует новое определение F
. Я должен переопределить show
, чтобы он распознал новое определение +
. В mit-схема
оба новых определения распознаются сразу, что я и ожидал. Кроме того, любые дальнейшие определения +
немедленно распознаются обоими интерпретаторами без необходимости переопределения show
.
Что ' что происходит за кулисами в guile
, чтобы заставить его связывать ссылки на эти переопределенные операторы по-разному?
И почему разница между двумя интерпретаторами?
Похоже, Guile ошибочно полагает, что никто не настолько сумасшедший, чтобы переопределить +
, и оптимизирует складывание ] (+ 2 2) => 4
, в результате чего (дисплей (+ 2 2))
становится (дисплей 4)
. Это объясняет, почему вам нужно переопределить show
, чтобы отразить ваш новый +
.
Действительно, если вы сначала выполните (define (+ ab) 4)
в самом начале своей программы, Guile не будет выполнять эту оптимизацию, и вы получите 4,4
и 5,5
точно так же, как MIT Scheme.
Изменить: На самом деле похоже, что Guile оптимизирует +
для ссылки на свою собственную конструкцию +
, что означает, что даже если вы не используете константы (без констант сворачивание), вы все равно не сможете переопределить +
таким образом.