LINUX.ORG.RU

Lisp: (gensym)

 gensym,


0

1

И снова здравствуйте!

От чего-то не работает конструкция вида:

(let ((#:sta 5)) (print #:sta))

Это опять же, пример. На самом деле подобные символы генерит
функция gensym. Но имена, сгенерированные ей, можно использовать
только с setf, Но никак не с let. Это фича такая? Или ситуацию можно исправить?
Спасибо.


Common Lisp читаю только со словарём, но, думаю, дело в том, что gensym возвращает символы. Так что она с let не работает по той же причине, по которой не работает

(let (('x 5)) (print x))
Тогда как setf способна принимать имена переменных в виде символов и присваивать им значения.

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

Интересно, а вот я увидел раскрытие макроса destructuring-bind:

(LET ((#:WHOLE1000 (LIST 1 2 3)))
  (DECLARE (TYPE LIST #:WHOLE1000))
  (LET* ()
    (DECLARE (SB-EXT:MUFFLE-CONDITIONS SB-EXT:CODE-DELETION-NOTE))
    (LET ((#:ARGS1002 #:WHOLE1000))
      (UNLESS (SB-INT:PROPER-LIST-OF-LENGTH-P #:ARGS1002 3 3)
        (SB-KERNEL::ARG-COUNT-ERROR 'DESTRUCTURING-BIND 'NIL #:ARGS1002
                                    '(X Y Z) 3 3)))
    (LET* ((X (CAR #:WHOLE1000))
           (Y (CAR (CDR #:WHOLE1000)))
           (Z (CAR (CDR (CDR #:WHOLE1000)))))
      (LIST :X Y :Y X :Z Z))))
Может, это declare ?

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

Не думаю. С # обычно начинается что-то специальное. В Common Lisp это макросы синтаксического анализатора. Судя по этому, #: тоже создаёт символы.

Так что #:FOO это (почти) то же самое, что и 'foo. И не работает с let по той же причине. А в распечатке раскрытия они показаны так, чтобы отличать от обычных символов. foo и #:foo — это разные вещи. Первое это просто символ, который трактуется как имя переменной, значение которой сюда надо подставить. Второе — это выражение, возвращающее символ. Поэтому его нельзя использовать в том месте let, где ожидается имя переменной, записанное буквально. Это как объявить функцию, назвав аргумент 'foo или #:foo

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

Я тут тоже рою по этому вопросу. На самом деле символы вида #:xxx
Называются внепакетными. Но в PCL их обошли вниманием и написали совсем мало.
Ни описания свойств, ни чего такого...

solom
() автор топика

покури, что такое символы

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

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

foo — символ (как литерал). 'foo или #:foo — это выражения, которые возвращают символы.

ilammy ★★★
()

Если кратко:

foo

- процедура чтения вернёт это как символ, итерированный в текущий пакет.

'foo

- процедура чтения вернёт это как список

(quote foo)
, где quote - специальный оператор.

#:foo

- процедура чтения вернёт это как новый неитерированный символ. Хитрость в том, что елди у тебя в коде есть несколько #:foo, то это разные символы.

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

Функция gensym возвращает новый неитерированный символ с именем «G» + номер. «G» можно поменять на другую строку, если передать её в gensym как параметр. Как так неитерированные символы даже с одинаковым именем - это разные символы, суть номера исключительно в том, чтоб раскрытия вложенных макросов были читабельны.

anonymous
()
Ответ на: комментарий от ados

У них же гигиены нету - приходится генерить символы для локальных переменных, например.

anonymous
()
Ответ на: комментарий от ados

Это объекты, которые идентифицируются по указателю. Результат gensym присваивается переменной внутри макроса, а затем может быть несколько раз вставлен в генерируемый код.

anonymous
()

Почему не работает, всё работает:

> (eval (let ((sta (gensym)))
          `(let ((,sta 5))
             (print ,sta))))
5
5

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

Точно! Спасибо! Их нужно сохранять в переменных

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

Верно. Я почему-то всегда произношу это слово неправильно.

anonymous
()
Ответ на: комментарий от naryl

По-моему именно этого он и хочет, но не знает, как задать произвольное имя символа.

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