Проблема с LISP-гензимом и функциями Let - PullRequest
2 голосов
/ 06 января 2020

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

I ' m используя функцию gensym для генерации чисел, соответствующих состояниям NFA, только я хотел бы взять только ее часть с цифрой c, используя *gensym-counter*, все работало нормально, но внезапно я столкнулся эта странная проблема:

Функция, которую я использую для вызова gensym, это

(defun gensympp ()
  (let ((x (gensym)))
    *gensym-counter*))

, поэтому она возвращает только увеличенное число после вызова gensym на x, поэтому я могу использовать ее для NFA заявляет, что сегодня я проводил несколько финальных тестов, и внезапно функция больше не увеличивает *gensym-counter*, поэтому каждое состояние - это только начальный номер (задается с помощью let в начале функции), единственный способ исправить похоже, в начале кода ставится (defparameter x 1) (число не имеет значения), при этом gensym обновляется нормально, и все работает нормально, как b поэтому я действительно понятия не имею, что могло вызвать это, потому что я только внес небольшие коррективы в форматирование кода, который прекрасно работал неделю * go, я тоже новичок в lisp, так что может быть что-то очевидное, я игнорирую, если нужно, я могу опубликовать оставшуюся часть кода, где я использую gensym, но даже сам вызов функции (gensympp) из слушателя не увеличивает число

Большое спасибо заранее за помощь

Ответы [ 3 ]

5 голосов
/ 06 января 2020

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

(defun gensympp ()
  (let ((x (gensym)))
    (values *gensym-counter* x)))
1 голос
/ 06 января 2020

Полагаю, что ваш профессор хочет заново перечислить состояния для каждого экземпляра NFA, начиная с 0 или 1. То есть счетчик состояний - это не глобальная переменная, а переменная экземпляра в некоторых Объект контекста построения NFA.

(Если подумать, эта непротиворечивая нумерация облегчит чтение ваших машин NFA людьми, в какой бы форме вы их не создавали. Если вы создадите один и тот же NFA дважды, оба будут согласуйте в форме графика и нумерацию состояний. Все учебные примеры этого материала, которые я когда-либо видел, нумеруют состояния от 0 или 1 в каждой последующей диаграмме.)

Обратите внимание также что вы можете присвоить пользовательский префикс gensym, который может быть пустой строкой:

[1]> (gensym "")
#:3318

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

0 голосов
/ 07 января 2020

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

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

Это может быть просто целое число, но на самом деле вы можете захотеть что-то изменяемое. Есть много способов сделать это. Один простой - это

(defun make-counter (&key (initial-value 0)
                          (increment 1))
  (let ((current (- initial-value increment)))
    (lambda ()
      (incf current increment))))

(defun next-count (counter)
  (funcall counter))

Сейчас:

> (loop with counter = (make-counter :increment 3)
             repeat 4
             collect (next-count counter))
(0 3 6 9)

Но есть много других.

В вопросе вы говорите, что связываете *gensym-counter* сами. Что ж, если это то, что вы делаете, то просто используйте свою собственную специальную переменную: она даже не должна быть глобальной:

(defmacro with-counter ((&key (initial-value 0)) &body forms)
  `(let ((%the-count% (1- ,initial-value)))
     (declare (special %the-count%))
     ,@forms))

(defun next-count ()
  (declare (special %the-count%))
  (unless (boundp '%the-count%)
    (error "not in dynamic extent of WITH-COUNTER"))
  (incf %the-count%))
...