Always when I start to try packages for Common Lisp GUI programming I encounter problems at a very early stage. I'm using SBCL 2.1.1 and 2.3.8 with Debian "Bullseye" and currently, I want to understand its usage with the LTk Examples.
The hello world example in the (with-nodgui () ) is no problem. Yet if it comes to the "first (real) example" starting with
(wm-title *tk* "Feet to Metres")
I end up in the debugger with the condition mentioned in the subject of this post (in Slime such as in the shell).
You can easily recognise that I am the contrary of an expert since such error messages always overwhelm my abilities to find a starting point for searching the cause.
When I tried to compile the following LET-form of the example without the WM-TITLE
(let ((content (make-instance 'frame)))
(...))
the error message kept the same.
Is it posssible that you can give me a hint how to avoid it? That would be a kind of an early christmas present for me.
(I was close to "crosscheck" whether it is a problem with the rigidity of SBCL by trying out CLisp. Yet I had to realise, that therefore I have to get involved into some initial configuration work for setting up CLisp since it didn't want to quickload :nodgui out-of-the-box, let alone find ASDF ... And I really(!) do not want to open a new box of annoying [a posteriori tiny little] problem areas. I just want to follow the examples to design the GUI I want to have WITHOUT ending up in the debugger without knowing why - making me cry ... and I want to do it with SBCL)
Best regards
P.S.: It might be helpful, to mind the Backtrace - yet at this level unfortunately not for me.
Backtrace:
0: ((FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN FLUSH-WISH))
1: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK))
2: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK #<FUNCTION (FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN FLUSH-WISH) {53B59E7B}> #<SB-THREAD:MUTEX "Anonymous recursive lock" taken owner=worker> T NIL)
3: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK))
4: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK #<FUNCTION (FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN NODGUI::SEND-WISH) {7F325273612B}> #<SB-THREAD:MUTEX "Anonymous recursive lock" taken owner=worker> T NIL..
5: (NODGUI::SEND-WISH "wm title . {Feet to Metres}")
Locals:
#:ITEM = "wm title . {Feet to Metres}"
6: ((:METHOD WM-TITLE (WIDGET T)) #<WIDGET {10079B22E3}> "Feet to Metres") [fast-method]
Locals:
TITLE = "Feet to Metres"
NODGUI::W = #<WIDGET {10079B22E3}>
7: (SB-INT:SIMPLE-EVAL-IN-LEXENV (WM-TITLE *TK* "Feet to Metres") #<NULL-LEXENV>)
8: (EVAL (WM-TITLE *TK* "Feet to Metres"))
9: ((LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL))
10: (SWANK::CALL-WITH-RETRY-RESTART "Retry SLIME interactive evaluation request." #<FUNCTION (LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL) {1008258DAB}>)
11: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<FUNCTION (LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL) {1008258D8B}>)
Locals:
FUN = #<FUNCTION (LAMBDA () :IN SWANK:INTERACTIVE-EVAL) {1008258D8B}>
PACKAGE = NIL
12: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")") #<NULL-LEXENV>)
13: (EVAL (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")"))
14: (SWANK:EVAL-FOR-EMACS (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")") "COMMON-LISP-USER" 38)
Locals:
BUFFER-PACKAGE = "COMMON-LISP-USER"
CONDITION = #<TYPE-ERROR expected-type: STREAM datum: NIL>
FORM = (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")")
ID = 38
OK = NIL
RESULT = NIL
15: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
[No Locals]
16: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<FUNCTION (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {539F452B}>)
17: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "/home/.../sbcl.lisp") #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<FUNC..
18: (SWANK::CALL-WITH-BINDINGS ((*STANDARD-INPUT* . #<SWANK/GRAY::SLIME-INPUT-STREAM {10018609B3}>)) #<FUNCTION (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {539F47DB}>)
19: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
20: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN))
21: ((FLET "WITHOUT-INTERRUPTS-BODY-174" :IN SB-THREAD::RUN))
22: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN))
23: ((FLET "WITHOUT-INTERRUPTS-BODY-167" :IN SB-THREAD::RUN))
24: (SB-THREAD::RUN)
25: ("foreign function: call_into_lisp_")
26: ("foreign function: funcall1")
Maybe is it how you load everything. Let's start from scratch:
(defpackage :feet-to-meter
(:use :cl :nodgui))
(in-package :feet-to-meter)
(defun feet-to-meter ()
(with-nodgui ()
(wm-title *tk* "Feet to Metres") ; 1
(let ((content (make-instance 'frame))) ; 2
(configure content :padding "3 3 12 12") ; 3
(grid content 0 0 :sticky "nsew")
(grid-columnconfigure *tk* 0 :weight 1)
(grid-rowconfigure *tk* 0 :weight 1)
(let* ((feet-entry (make-instance 'entry :master content :width 7)) ; 4
(metres-label (make-instance 'label :master content :text "")))
(flet ((calculate () ; 5
(let ((feet (read-from-string (text feet-entry))))
(setf (text metres-label)
(if (numberp feet)
(/ (round (* 0.3048 feet 10000.0)) 10000.0)
"")))))
; top row has the entry widget and explanatory label to its right
(grid feet-entry 1 2 :sticky "we" :padx 5 :pady 5) ; 6
(grid (make-instance 'label :master content :text "feet")
1 3 :sticky "w" :padx 5 :pady 5)
; middle row has three labels
(grid (make-instance 'label :master content :text "is equivalent to")
2 1 :sticky "e" :padx 5 :pady 5)
(grid metres-label 2 2 :sticky "we" :padx 5 :pady 5)
(grid (make-instance 'label :master content :text "metres")
2 3 :sticky "w" :padx 5 :pady 5)
; last row has the button on right
(grid (make-instance 'button :master content ; 7
:text "Calculate"
:command #'calculate)
3 3 :sticky "w" :padx 5 :pady 5)
(focus feet-entry) ; 8
(bind *tk* "<Return>" (lambda (evt) (calculate))))))
))
try it:
FEET-TO-METER> (feet-to-meter)