Ошибка SBCL: «Нет переменных отладки для текущего кадра: используется EVAL вместо EVAL-IN-FRAME». - PullRequest
0 голосов
/ 17 мая 2018

Я новичок в Лиспе, использую SBCL 1.2.11 из терминала.

Может ли кто-нибудь помочь мне понять, с чего мне начать искать, чтобы избавиться от вышеуказанной ошибки?Я думаю, что это вызывает у меня следующую ошибку:

(setf x (list 'a 'b 'c)) 
; No debug variables for current frame: using EVAL instead of EVAL-IN-FRAME.
; (SETF X (LIST 'A 'B 'C)) ; ==> ; (SETQ X (LIST 'A 'B 'C)) 
; ; caught WARNING: ; undefined variable: X ; ; compilation unit finished 
; Undefined variable: ; X ; caught 1 WARNING condition (A B C)

Я не должен видеть комментарии, верно?Большое вам спасибо!

1 Ответ

0 голосов
/ 22 мая 2018

[Я добавил этот ответ, поскольку, похоже, других нет и надеюсь, что он может помочь.]

Здесь есть две проблемы:

  • вы делаете что-то, что не является законным Common Lisp (как правило, это делается);
  • SBCL предупреждает об этом в несколько неинформативном ключе.

Есть важная часть терминологии, которая распространена в Лиспе, но я думаю, что она менее распространена в других языках. Эта терминология является привязкой : привязка - это, по сути, связь между именем какого-либо вида и значением. С привязкой связаны область действия - , где она видима, и степень , , когда она видима. (Я не буду говорить о масштабах и масштабах, потому что это большой вопрос, и этот ответ уже слишком длинный.) Почти все языки программирования имеют эти три понятия, но они часто называют их разными вещами в замешательстве.

То, что часто называют переменной, - это имя, которое связано со значением: на самом деле это привязка. И, конечно же, термин «связывание» происходит от «связывания переменных». Но не все привязки являются переменными - термин теперь более общий и более точный (хотя я не даю здесь ничего подобного точному определению).

Существует два семейства конструкций, которые имеют дело с привязками:

  • конструкции, которые устанавливают привязки;
  • конструкции, которые изменяют привязки.

Эти две вещи отличаются в CL. Как и во многих языках программирования, существуют специальные конструкции, которые создают привязки, и другие конструкции, которые изменяют (мутируют) их. Конструкции, которые изменяют привязки , требуют, чтобы привязки существовали , чтобы их можно было изменять.

Конструкции, которые устанавливают привязки

В CL Это такие вещи, как let: (let ((x 1) y) ...) устанавливает локальные привязки для x и y, видимых в его лексической области видимости (обычно). defvar и друзья устанавливают глобальные привязки. defun и друзья устанавливают глобальные привязки в другом пространстве имен (пространстве имен функций, в отличие от пространства имен переменных) в CL, а flet / labels устанавливают локальные привязки функций. Существуют и другие конструкции, и, в частности, набор конструкций эффективно расширяется пользователем обычным способом Lisp.

Конструкции, которые изменяют привязки

Традиционной конструкцией для изменения привязки переменной является setq: setf - это макрос, который позволяет вам изменять привязки (и другие вещи, которые он называет «местами», такими как элементы массивов) в более общем и пользовательском расширяемый способ. Таким образом, (setf x 2) изменяет привязку x.

Ошибка

Ошибка, которую вы делаете, состоит в том, что вы не можете просто сказать (setf a ...), если не существует существующего связывания a. Этот код недопустим CL:

(defun foo ()
  (setf a 1)
  ...)

Вместо этого вам нужно установить привязку для a:

(defun foo ()
  (let ((a ...))
    ...
    (setf a 1)
    ...))

Ну, то же самое верно на верхнем уровне : вы не можете просто сказать:

> (setf x (list 'a 'b 'c))

потому что * вы пытаетесь изменить привязку x, которая не существует.

И это то, что SBCL говорит вам довольно неинформативным (я думаю) образом: оно говорит вам, что не существует привязки x.

Решения и решения

К сожалению, CL на самом деле не предлагает очень хорошего решения этой проблемы. Один из способов «решить» это сделать это:

> (defvar x ...)
[...]
> (setf x (list 'a 'b 'c))

Но это нежелательное решение: (defvar x ...) превращает x в глобально специальную переменную - переменную, которая динамически ограничена. Это изменяет семантику любой привязки x, например, в более поздней функции, способами, которые могут быть неожиданными. Это нежелательно. Если вы хотите это сделать, хотя бы убедитесь, что ваши специальные переменные соответствуют соглашению *star*, поэтому очевидно, что они есть.

CL, «из коробки» не предлагает то, что вам может понадобиться, это «лексические переменные верхнего уровня» - привязки переменных, которые вы можете объявить на верхнем уровне, которые не сделать эту несчастную глобально-особенную вещь.Однако Lisp настолько гибок, что вы действительно можете добавить это к нему, если хотите.

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

И во многих реализациях это работает: интерактивная среда верхнего уровня позволяет вампросто скажите это и просто делаете правильные вещи, в то время как когда вы, например, компилируете файл, вы получите предупреждение во время компиляции и ошибку времени выполнения (возможно, предупреждение), если вы сделаете то же самое.Однако такое непринужденное поведение в интерактивной среде совершенно явно выходит за рамки стандарта.

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


Способ не решить проблему

Один из способов, который может показаться разумным для решения этой проблемы, это просто не иметь специальных конструкций для создания привязок: привязка создается при первом назначении,Это то, что делает, например, Python.Внешне это выглядит как хитрый трюк: здесь меньше печатания и суеты.

Но какова цель этих неявно созданных привязок?(Python говорит «вся функция, включая ее части, которые запускаются до первого присваивания», что, в общем-то, интересно.) И, что еще хуже, как вы различаете что-то, что является присваиванием переменной, определенной во внешнемscope и идентичная конструкция, которая создает привязку во внутренней области: хорошо, вы делаете это с помощью специальной «глобальной» конструкции ... которая на самом деле не работает: Python теперь также имеет «нелокальную» конструкцию .И как вы скажете, связана ли переменная или нет во время компиляции (или даже, действительно, во время выполнения), чтобы выдавать хорошие предупреждения?

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

...