Почему SBCL жалуется на setf? - PullRequest
4 голосов
/ 29 апреля 2020

В SBCL это присваивает 'bar foo с предупреждениями:

* (setf foo 'bar)
; in: SETF FOO
;     (SETF FOO 'BAR)
; ==>
;   (SETQ FOO 'BAR)
; 
; caught WARNING:
;   undefined variable: COMMON-LISP-USER::FOO
; 
; compilation unit finished
;   Undefined variable:
;     FOO
;   caught 1 WARNING condition
BAR
* 

Следующее от Touretzky. Я набрал это в «7.29.lisp» и сохранил.

(setf database
’((b1 shape brick)
(b1 color green)
(b1 size small)
(b1 supported-by b2)
(b1 supported-by b3)
(b2 shape brick)
(b2 color red)
(b2 size small)
(b2 supports b1)
(b2 left-of b3)
(b3 shape brick)
(b3 color red)
(b3 size small)
(b3 supports b1)
(b3 right-of b2)
(b4 shape pyramid)
(b4 color blue)
(b4 size large)
(b4 supported-by b5)
(b5 shape cube)
(b5 color green)
(b5 size large)
(b5 supports b4)
(b6 shape brick)
(b6 color purple)
(b6 size large)))

После чего:

* (load "7.29.lisp")
While evaluating the form starting at line 1, column 0
  of #P"/home/redacted/7.29.lisp":

debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "main thread" RUNNING {10005D05B3}>:
  odd number of args to SETF: (SETF DATABASE ’
                                    ((B1 SHAPE BRICK) (B1 COLOR GREEN)
                                     (B1 SIZE SMALL) (B1 SUPPORTED-BY B2)
                                     (B1 SUPPORTED-BY B3) (B2 SHAPE BRICK)
                                     (B2 COLOR RED) (B2 SIZE SMALL)
                                     (B2 SUPPORTS B1) (B2 LEFT-OF B3)
                                     (B3 SHAPE BRICK) (B3 COLOR RED) ...))

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [RETRY   ] Retry EVAL of current toplevel form.
  1: [CONTINUE] Ignore error and continue loading file "/home/redacted/7.29.lisp".
  2: [ABORT   ] Abort loading file "/home/redacted/7.29.lisp".
  3:            Exit debugger, returning to top level.

(SB-C::EXPLODE-SETQ (SETF DATABASE ’ ((B1 SHAPE BRICK) (B1 COLOR GREEN) (B1 SIZE SMALL) (B1 SUPPORTED-BY B2) (B1 SUPPORTED-BY B3) (B2 SHAPE BRICK) (B2 COLOR RED) (B2 SIZE SMALL) (B2 SUPPORTS B1) (B2 LEFT-OF B3) (B3 SHAPE BRICK) (B3 COLOR RED) ...)) ERROR)
0] 

Что мне нужно понять, чтобы SBCL доволен этими назначениями?

Ответы [ 2 ]

9 голосов
/ 29 апреля 2020

это первое предупреждение мне кажется довольно ясным, че. в (setf foo 'bar), foo, как известно, не ссылается на переменную. он не был локально связан как лексическая переменная с помощью формы, подобной lambda или let, и не был глобально связан как специальная переменная с помощью формы, подобной defvar или defparameter. если вы хотите, чтобы это выглядело как форма верхнего уровня, вы должны написать (defparameter *foo* 'bar) (обратите внимание, что общепринятым соглашением lisp является окружение имен специальных переменных в наушниках). если вы хотите сделать это в теле функции или для конечной области видимости, вы должны сделать (let ((foo 'bar)) (do-stuff-with foo)).

относительно вашей второй проблемы, в дополнение к тому факту, что database не связан, вы иметь неправильный символ кавычки. не является одиночной кавычкой ascii, и поэтому анализируется как символ. компилятор видит вашу форму как: (setf database |’| ((b1 shape green) ...)), которая не является действительной setf формой. чтобы это исправить, выясните, как набирать символ ' и / или не копировать и не вставлять код из отформатированных документов в текстовые файлы.

3 голосов
/ 29 апреля 2020

В то время как в ответе Фиби подводит итог, я бы хотел добавить контекст, который мне не хватает.

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

Глобальные переменные вводятся с использованием defvar, defparameter, а локальные переменные с использованием let, let*, lambda и тому подобное. Однако речь идет не только о том, чтобы быть глобальным или локальным - см. этот вопрос о динамичности c против лексической области видимости .

После того, как вы ввели переменные с помощью вышеуказанных средств, вы можете использовать setf для назначения.


В CLHS используются следующие правильные термины:

defvar, defparameter

defparameter и defvar установить sh имя в качестве динамической c переменной.

Ссылка: http://clhs.lisp.se/Body/m_defpar.htm

let, let *

let и let* создают новые привязки переменных ...

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

Ссылка: http://clhs.lisp.se/Body/s_let_l.htm#let

setf

setf изменяет значение места на новое значение.

Ссылка: http://clhs.lisp.se/Body/m_setf_.htm

Редактировать: учел комментарий @ tfb и CLHS.

...