LINUX.ORG.RU

Вылетает Unbound variable

 ,


0

2
(defclass coloured ()
  (colour))

(defclass coloured-circle (circle coloured)
  ())

(defclass rectangle ()
  (height width))

(defclass circle ()
  (radius))

(defvar r)
(defmethod area-r ((r rectangle))
  (* (slot-value r 'height)
     (slot-value r 'width)))

(defvar c)
(defmethod area-c ((c circle))
  (* pi (expt (slot-value c 'radius) 2)))

(let ((r (make-instance 'rectangle)))
  (setf (slot-value r 'height) 2
	(slot-value r 'width) 3)
  (area-r r))

(let ((c (make-instance 'circle)))
	(setf (slot-value c 'radius) 4)
  (area-c c))

(defvar cc)
(let ((cc (make-instance 'coloured-circle)))
  (setf (slot-value cc 'radius) 9)
  (area-c cc))
CL-USER> (defvar cc)
CC
CL-USER> (let ((cc (make-instance 'coloured-circle)))
  (setf (slot-value cc 'radius) 9)
  (area-c cc))

254.46900494077323d0
CL-USER> (type-of cc)
; Evaluation aborted on #<UNBOUND-VARIABLE CC {100460B1B3}>. ->

 какова техника поиска, что я проморгал? 

Почитай доки, ну:

If no initial-value is supplied, defvar leaves the value cell of the dynamic variable named name undisturbed; if name was previously bound, its old value persists, and if it was previously unbound, it remains unbound.

let создаёт локальное связывание, которое действительно только на время жизни блока.

PS. Тебе не нужно объявлять переменные для let и параметры функций/методов через defvar.

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

Я привёл не совсем удачный пример. Смотрю сюда

http://www.lispworks.com/documentation/HyperSpec/Body/f_mk_ins.htm#make-instance

(defclass circle ()
  (radius))

(defmethod area ((c circle))
  (* pi (expt (slot-value c 'radius) 2)))


пишу
(area (make-instance 'circle (setf (slot-value c 'radius) 7)))
получаю
; Evaluation aborted on #<UNBOUND-VARIABLE C {100323C5D3}>.

что делать ума не приложу

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

(setf (slot-value c 'radius) 7)

А почему это вообще должно работать? make-instance принимает название класса и список инициализации аргументов, а не произвольные выражения. Почему вообще (setf (slot value c ...)) должен работать, если сам c не объявлен? (Напоминаю, параметр c метода area является локальным для самого метода, т.е. извне он не существует.)

Если ты хочешь проинициализировать слот при создании инстанса, то это делается примерно так:

(defclass circle ()
  ((radius
   :initarg :radius))

(defmethod area ((c circle))
  (* pi (expt (slot-value c 'radius) 2)))

(area (make-instance 'circle :radius 7))

(Код не проверял, так что не уверен, что он работает; у меня не стоит интепретатор CL, я вообще не пишу на CL, я просто по нему одну книжку 10 лет назад прочитал.)

Выглядит так, как будто ты не совсем понимаешь, что ты делаешь (причём как в плане языка, так и в плане CLOS). Почитай какую-нибудь книгу по языку, даже тот же PCL (там есть и главы про CLOS).

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

Выглядит так, как будто ты не совсем понимаешь, что ты делаешь (причём как в плане языка, так и в плане CLOS).

Это действительно так, потому что кажется, что это не ЛИСП. Читаю ANSI Common Lisp by Paul Graham, а также Sonia Keen Object bla bla. Я чего-то не догоняю, когда с ЛИСП познакомился так я вообще никаких книжек не читал, писал уравнения на ЛИСП и всё. Может вообще зря лезу в CLOS.

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

Почему вообще (setf (slot value c ...)) должен работать, если сам c не объявлен?

Тоже странность, вот эта конструкция работает, хотя тут let определяет с

CL-USER> (let ((c (make-instance 'circle)))
	(setf (slot-value c 'radius) 4)
  (area-c c))
50.26548245743669d0
CL-USER> 

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

saufesma
() автор топика
Последнее исправление: saufesma (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

Выглядит так, как будто ты не совсем понимаешь, что ты делаешь (причём как в плане языка, так и в плане CLOS).

Так и есть. ТС уже не первый год тут страдает с лиспом. Наверное, просто необучаемый.

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

Тоже странность, вот эта конструкция работает, хотя тут let определяет с

В let с виден только внутри.

(let ((c ..)) здесь c доступен)

а здесь c уже нет
monk ★★★★★
()
Ответ на: комментарий от monk

Хорошо, а это как

;;;CL-USER> (defvar c)
;;;C
;;;CL-USER> (area (make-instance 'circle (setf (slot-value c 'radius) 7)))
;;;; Evaluation aborted on #<UNBOUND-VARIABLE C {1004BCC203}>.
saufesma
() автор топика
Ответ на: комментарий от saufesma

Тоже странность, вот эта конструкция работает, хотя тут let определяет с

Потому что let объявляет переменную («связывание»), которая существует только на протяжении жизни блока let (тут на самом деле всё немного сложнее, но это не важно) и уничтожается при выходе из него. Я об этом писал тут.

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

Я чего-то не догоняю, когда с ЛИСП познакомился так я вообще никаких книжек не читал, писал уравнения на ЛИСП и всё. Может вообще зря лезу в CLOS.

Судя по всему, ты не только CLOS не можешь понять, но и сам Common Lisp. Может, стоит выбрать язык попроще, по которому и документации, и книжек больше будет?

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

Хорошо, а это как

  1. defvar без начального значения не создаёт переменную, если она не была ранее объявлена. Я про это уже скидывал цитату из доки тут.
  2. Как в твоём понимании происходит вычисление (make-instance 'circle (setf (slot-value c 'radius) 7))? Почему ты вообще пихаешь в initializer list выражение с setf? Ты вообще предствляешь, как устроен порядок вычислений в ЯП? Что тут значение аргументов функции вычисляется до отправки их в функцию (eager-вычисления), а результат функции можно получить, только сначала вычислив эту функцию? А не дёргать слот объёкта ещё до того, как он был создан.

Вот ещё работающий пример (в дополнение к примеру выше):

(defvar c (make-instance 'circle)) # СНАЧАЛА мы создаём объект
(setf (slot-value c 'radius) 7) # ТОЛЬКО ПОТОМ дёргаем его слот
(area c)

PS. Это будет моё последнее сообщение по теме.

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

PS. Это будет моё последнее сообщение по теме.

Ну блин, на самом интересном месте. И уже не первый раз.

Ты вообще предствляешь, как устроен порядок вычислений в ЯП?

Очень близко, к не представляю.

Что тут значение аргументов функции вычисляется до отправки их в функцию (eager-вычисления), а результат функции можно получить, только сначала вычислив эту функцию? А не дёргать слот объёкта ещё до того, как он был создан.

Ну почему мне так не везёт.

saufesma
() автор топика
Последнее исправление: saufesma (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.