Различия между Sharpsign Colon и Gensym

Я только что читал о макросе для считывания толстой кишки с акцентом на знаке, и мне показалось, что он имеет очень похожий эффект на gensym

Двоеточие с острым знаком: «вводит неискаженный символ».

Gensym: «Создает и возвращает свежий, неискаженный символ»

Итак, простой тест

CL-USER> #:dave
; Evaluation aborted on #<UNBOUND-VARIABLE DAVE {1002FF77D3}>.
CL-USER> (defparameter #:dave 1)
#:DAVE
CL-USER> #:dave
; Evaluation aborted on #<UNBOUND-VARIABLE DAVE {100324B493}>.

Круто так что не получается как надо.

Теперь о макро-тесте

(defmacro test (x)
  (let ((blah '#:jim))
    `(let ((,blah ,x))
       (print ,blah))))

CL-USER> (test 10)

10 
10
CL-USER>

Сладкий, поэтому его можно использовать в качестве генсима.

На мой взгляд, это выглядит чище, чем gensym, с явно идентичным результатом. Я уверен, что упускаю важную деталь, поэтому мой вопрос: что это?


person Baggers    schedule 02.02.2015    source источник


Ответы (2)


GENSYM похож на MAKE-SYMBOL. Разница в том, что GENSYM поддерживает причудливое именование путем подсчета -> таким образом символы имеют уникальные имена, что немного упрощает отладку при наличии генсимов, например, в расширениях макросов.

#:foo - обозначение для читателя.

Итак, у вас есть функция, которая их создает, и буквальные обозначения. Обратите внимание, что, когда *print-circle* истинно, в s-выражениях может сохраняться какая-то идентичность: #(#1=#:FOO #1#).

Обычно это похоже на (a . b) и (cons 'a 'b), #(a b) и _10 _... Один - это буквальные данные, а другой - форма, которая будет создавать («против») свежие объекты.

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

  • лексически это может быть та же самая переменная, которая является рикошетом.

  • динамически, если это специальная переменная, она также может быть восстановлена

Использование сгенерированного символа во время раскрытия макроса гарантирует, что другой и расширенный код не будет иметь общих привязок.

person Rainer Joswig    schedule 02.02.2015
comment
Ах да, я не тратил время на размышления о последствиях захвата, в чем, очевидно, все дело ... ух! Спасибо за это - person Baggers; 02.02.2015

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

(defmacro foo () `(quote #:x))
(defmacro bar () `(quote ,(gensym)))

(eq (foo) (foo)) => t
(eq (bar) (bar)) => nil

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

Хотя использование острого двоеточия вряд ли вызовет проблемы, есть пара редких случаев, когда его использование приведет к почти невозможному поиску ошибок. Лучше начать с того, что всегда будет использовать gensym.

Если вы хотите использовать что-то вроде острого двоеточия, вам следует взглянуть на defmacro! макрос из Let Over Lambda.

person malisper    schedule 02.02.2015
comment
Пригвожденный, я был пустышкой из-за того, что не думал о захвате. Я даже прочитал "let over lambda", так что сегодня я действительно был болваном, хе-хе - person Baggers; 02.02.2015