← Архив: Common Lisp

Не могу найти ошибку

Author: · 03.02.2011 12:43
· original author: Paul.Alkhimov
Подскажите, как отлаживать код на лиспе. Никак не могу найти края, за который можно было бы распутать ошибку.
Вот код, где точно ошибка:
(defclass kd-node ()
  ((split-position :initarg :split
                   :initform 0.0
                   :accessor :split
                   :type coordinate
)
)

  ((left :initarg :left
         :accessor :left
)
)

  ((right :initarg :right
          :accessor :right
)
)

  (:documentation "If both branches are available, it is a node. If a the LEFT has something and the RIGHT is nil, it is a leaf and the LEFT has the contents of the leaf.")
)

Мне говорит такое:
keyword argument not a symbol:
(LSRT-TYPES::LEFT :INITARG :LEFT :ACCESSOR :LEFT).
  [Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]

Restarts:
// выбросил для экономии места

Backtrace:
 0: (SB-PCL::CHECK-APPLICABLE-KEYWORDS 0 T 571809 18)
 1: ((LAMBDA (SB-PCL::.PV. SB-PCL::.NEXT-METHOD-CALL. SB-PCL::.ARG0. SB-PCL::.ARG1. SB-INT:&MORE SB-PCL::.DFUN-MORE-CONTEXT. SB-PCL::.DFUN-MORE-COUNT.)) ..)
 2: (SB-MOP:ENSURE-CLASS LSRT-TYPES::KD-NODE)[:EXTERNAL]
 3: (SB-PCL::REAL-LOAD-DEFCLASS ..)
 4: ((SB-C::TOP-LEVEL-FORM ..))[:TOPLEVEL]
 5: (SB-FASL::LOAD-FASL-GROUP #<SB-SYS:FD-STREAM for "file d:\\Paul.revised\\git.repos\\github\\lsrt-types\\sbcl-1.0.37-win32-x86\\lsrt-types.fasl" {24984C71}>)
 6: ((FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK))
и так далее
Подскажите, как можно определить место ошибки? Дебаггер никак не помогает в этом: нет ни ссылок на нескомпилировавшиеся sexp-ы, ни точек в тексте, где что-то пошло не так. Просто, "файл не скомпилировался" и описание ошибки.
Если нужен код файла, то я дам отдельно, чтоб в топике не засорять.
· original author: lithp
слишком много сkобок и кивордов ;)
Здесь исправлено:
(defclass kd-node ()
  ((split-position :initarg :split
                          :initform 0.0
                          :accessor split
                         :type coordinate)
   (left :initarg :left
          :accessor left)
   (right :initarg :right
             :accessor right))
  (:documentation "If both branches are available, it is a node. If a the LEFT has something and the RIGHT is nil, it is a leaf and the LEFT has the contents of the leaf."))
· original author: Love5an
синтаксис defclass такой:
(defclass name (superclass*) (slot*) option*)
то есть, все слоты должны быть во вторых скобках, а не каждый в отдельной паре
кроме того, :accessor, по-хорошему, должен быть обычным символом, а не ключевым.:accessor вводит именованную функцию, с соответствующим именем
· original author: Paul.Alkhimov
ааа блин, точно! отступы не помогли, а я на них полагаюсь...
Да, по конкретной ошибке я понял.
Подскажите, как можно дебажить загружаемый код? В данном случае я знал, где ошибка и это большая помощь, но в общем случае - это жесть, комментировать куски кода и смотреть, изменяются ли сообщения об ошибках. (Это самый простой вариант, который я нашёл).
· original author: allchemist
Подскажите, как можно дебажить загружаемый код? В данном случае я знал, где ошибка и это большая помощь, но в общем случае - это жесть,
> комментировать куски кода и смотреть, изменяются ли сообщения об ошибках. (Это самый простой вариант, который я нашёл)

http://lisper.ru/articles/sbcl-debugging
А вапще с опытом должно появиться умение представлять источник ошибки сразу по сообщению отладчика в несложных случаях.
· original author: Paul.Alkhimov
жесть:
Обратная трассировка (backtrace) в SBCL на настоящий момент реализована не лучшим образом, не придавайте ей много значения. Просто загляните (вызовите любую ошибку) в REPL и выясните, что происходит. Поразвлекайтесь с штатным отладчиком SBCL и модным Slime Debugger, прежде чем будете пользоваться ими на практике, и тогда они перестанут казаться вам враждебными. О том, как пользоваться обратной трассировкой, я напишу в другой раз.
Это основной механизм, который я использовал в С-подобных и который я пытался применить здесь...
· original author: slav
> Обратная трассировка (backtrace) в SBCL на настоящий момент реализована не лучшим образом, не придавайте ей много значения
Нагло врут. Вполнне нормальная она, и с SLIME интегрируется нормально. Если компилировать с (debug 3) - так вообще всё замечательно.
· original author: allchemist
Нагло врутДумаю, человеку с именем Nikodemus Siivola в этом вопросе стои верить :)
Вероятно, он считает, что она могла быть сделана гораздо лучше.


Хотя ее ценность в лиспе, вообще говоря, сомнительна
· original author: slav
> Думаю, человеку с именем Nikodemus Siivola в этом вопросе стои верить :)
Сейчас посмотрел оригинал - блин, и кто это переводил? Фразу "
While SBCL backtraces aren't at the moment the pretties ones in the world, try to make sense out of them" можно перевести как "Хотя SBCL сейчас выдаёт обратную трассировку не в самом лучшем виде, постарайтесь всё же с ней разобраться". Но никак не так, как написано в русском переводе.
Доделывать там, наверное, есть что, но оно вполне годное и довольно удобное (не хуже (даже лучше во многом) чем backtrace в том же gdb).
· original author: archimag
> Сейчас посмотрел оригинал - блин, и кто это переводил? 
Ну, дык, ссылка там есть же ) Вообще, если есть возможность проверить перевод - то было бы здорово. Например, можно сейчас на wiki выложить "правильный", а я бы потом перенёс его в статьи.
· original author: 1349
Хотя ее ценность в лиспе, вообще говоря, сомнительна

Почему это? Я в лиспворксе частенько не только бэктрейс смотрю, но ещё и по стеку вверху-вниз хожу.
· original author: Paul.Alkhimov
В сиплюсплюсовом STL есть проблемы с выводом ошибок компиляции шаблонов. А именно - иногда компилятор вываливает много экранов логов простой ошибки, где невероятно сложно найти корень этой самой ошибки.
Так к чему я это: для конкретно этой проблемы было найдено решение в виде отдельной программы, которая эти логи ошибок анализирует и выдаёт их в удобочитаемом виде, выбрасывая внутренние, ненужные пользователю, промежуточные элементы.
Вопрос такой: а для SBCL есть что-то подобное, что извлекало бы из бэктрэйса только код пользователя, выкидывая кишки компилятора? Или это в принципе нерешаемая задача?
· original author: Love5an
По бектрейсу смотреть надо.Вот конкретно тут все понятно даже без кода:
Лисп-система вычисляет что-то в REPL: 4: ((SB-C::TOP-LEVEL-FORM ..))[:TOPLEVEL] Парсинг макроса DEFCLASS: 3: (SB-PCL::REAL-LOAD-DEFCLASS ..) ENSURE-CLASS это функция из метаобъектного протокола, в которую раскрывается DEFCLASS: 2: (SB-MOP:ENSURE-CLASS LSRT-TYPES::KD-NODE)[:EXTERNAL] Вызов метода этой обобщенной функции: 1: ((LAMBDA (SB-PCL::.PV. SB-PCL::.NEXT-METHOD-CALL. ..) ..) Метод обломался, так как принял ((left )) за option defclass'а. В опциях всегда первым аргументом должен идти keyword-символ, а тут - список. 0: (SB-PCL::CHECK-APPLICABLE-KEYWORDS 0 T 571809 18) keyword argument not a symbol: (LSRT-TYPES::LEFT :INITARG :LEFT :ACCESSOR :LEFT). [Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]
Пакет SB-PCL по-хорошему давно надо переименовать в SB-CLOS.
PCL расшифровывается как Portable Common Loops - это предок CLOS, объектной системы CL. Название еще из CMUCL осталось,  с тех пор, как тот был еще даже не CL, а Spice Lisp
· original author: Love5an
А что такое "код пользователя"? Функции? Функции он отлично показывает.Ошибки в стандартных макросах и функциях тоже понятны, в принципе.
А макросы из third-party библиотек это уже проблема не самого SBCL.
· original author: 1349
Ошибки в крестовых темплейтах более детерминированы, чем ошибки в S-выражениях. Что вот должен выдавать сторонний тулз на ошибку в программе на DSL, про который он ничего не знает и знать не может? 
· original author: allchemist
Сейчас посмотрел оригинал - блин, и кто это переводил?Я переводил. Как перевел, так оставил без изменения, вроде никто не захотел пробежаться по исходнику.
Спасибо за замечание, сегодня исправлю и заодно пройдусь по остальному тексту.


Почему это? Я в лиспворксе частенько не только бэктрейс смотрю, но ещё и по стеку вверху-вниз хожу.
Круто.
Но имхо отладочная печать в cl более полезна и удобна.
· original author: Paul.Alkhimov
> Но имхо отладочная печать в cl более полезна и удобна.
Вот я тоже на этом варианте пока что остановился. Не могу я запросто продраться через CLOS и подробности SBCL не имея понятия об их внутренностях.
Кстати, о внутренностях. Love5an, подскажи пожалуйста, откуда у тебя информация о семантике вызовов? Я вот почитал Соню Киин, у неё подробностей о MOPе нет. Есть только описание некоторых особенностей CLOS. Есть что-то об CLOS или SBCL в удобоваримой форме, кроме самих исходников?
· original author: Love5an
>Кстати, о внутренностях. Love5an, подскажи пожалуйста, откуда у тебя информация о семантике вызовов? Я вот почитал Соню Киин, у неё подробностей о MOPе нет. Есть только описание некоторых особенностей CLOS. Есть что-то об CLOS или SBCL в удобоваримой форме, кроме самих исходников?

AMOP. Плюс, вот тут вот можно почитать: http://lisp.org/mop/index.html
· original author: naryl
ИМХО здесь всё проще и понятнее. А главное на примере: http://infolab.stanford.edu/~paepcke/shared-documents/mopintro.ps
"it should come with a warning though - You might get an uncontrollable urge to make an ORM" (c) p_l