Зачем Scheme нужно специальное понятие тега местоположения процедуры?

Зачем в Scheme специальное понятие тега местоположения процедуры?
В стандарте сказано:

Каждая процедура, созданная в результате оценки лямбда-выражения, (концептуально) помечается местом хранения, чтобы сделать eqv? и экв.? работать над процедурами

Экв? процедура возвращает #t, если:

  • obj1 и obj2 — это процедуры, у которых тэги местоположения равны.

Экв.? и экв? гарантированно будут вести себя одинаково на... процедурах...

Но в то же время:

Переменные и объекты, такие как пары, векторы и строки, неявно обозначают местоположения или последовательности местоположений.

Экв? процедура возвращает #t, если:

  • obj1 и obj2 — это пары, векторы или строки, которые обозначают одни и те же места в хранилище.

Экв.? и экв? гарантированно будут вести себя одинаково на... парах... и непустых строках и векторах

Почему бы просто не применить «неявно обозначать местоположения или последовательности местоположений» и к процедурам?
Я думал, что это относится и к ним
Я не вижу ничего особенного в процедурах в этом отношении.


person Des Nerger    schedule 03.05.2014    source источник


Ответы (2)


Пары, векторы и строки изменяемы. Следовательно, идентичность (или местонахождение) таких объектов имеет значение.

Процедуры неизменяемы, поэтому их можно произвольно копировать или объединять без видимой разницы в поведении. На практике это означает, что некоторые оптимизирующие компиляторы могут встраивать их, фактически делая их «множественными копиями». R6RS, в частности, говорит, что для выражения типа

(let ((p (lambda (x) x)))
  (eqv? p p))

верность результата не гарантируется, так как он мог быть встроен как (eqv? (lambda (x) x) (lambda (x) x)).

Понятие тегов местоположения R7RS состоит в том, чтобы гарантировать, что это выражение действительно приводит к истинному результату, даже если реализация выполняет встраивание.

person Chris Jester-Young    schedule 03.05.2014
comment
Представьте пример со Сталиным (begin (define (f x) (lambda () x)) (eq? (f 1) (f 2))). Процедура та же, но закрытие отличается. Для меня не было очевидно, что R7RS оценит это как #f, так как я предполагал, что тег местоположения связан с лексическим местом в источнике. - person Sylwester; 05.05.2014
comment
@Sylwester Каждый вызов lambda генерирует новый тег местоположения, а не, как вы говорите, лексическое место в источнике. :-) Это аналогично тому, как каждый вызов list создает новый список. - person Chris Jester-Young; 05.05.2014

Обработка процедур как значений работает в таких языках, как ML, где они действительно неизменяемы. Но в Scheme процедуры действительно могут быть видоизменены, потому что могут быть изменены их локальные переменные. По сути, процедуры являются объектами для бедняков (хотя можно также утверждать, что объекты в стиле OO — это просто процедуры для бедняков!) Тег местоположения служит той же цели, что и идентификатор объекта, который различает две пары с идентичными автомобилями и cdr.

В частности, придание глобальной процедуре идентичности означает, что можно напрямую спросить, является ли предикат, который нам был передан, конкретно eq? или экв? или равно?, что невозможно для переноса в R6RS (хотя на практике возможно в реализациях R6RS).

person John Cowan    schedule 05.07.2014